2011 6.7.3.1 says:
1 Let D be a declaration of an ordinary identifier that provides a means of designating an object P as a restrict-qualified pointer to type T.
2 If D appears inside a block and does not have storage class extern, let B denote the block. If D appears in the list of parameter declarations of a function definition, let B denote the associated block. Otherwise, let B denote the block of main (or the block of whatever function is called at program startup in a freestanding environment).
3 In what follows, a pointer expression E is said to be based on object P if (at some sequence point in the execution of B prior to the evaluation of E) modifying P to point to a copy of the array object into which it formerly pointed would change the value of E. Note that "based" is defined only for expressions with pointer types.
4 During each execution of B, let L be any lvalue that has &L based on P. If L is used to access the value of the object X that it designates, and X is also modified (by any means), then the following requirements apply: T shall not be const-qualified. Every other lvalue used to access the value of X shall also have its address based on P. Every access that modifies X shall be considered also to modify P, for the purposes of this subclause...
Based on this sentence, I conceived a piece of code:
int main()
{
int A = 5;
int* restrict P;
P = &A;
*P = 10;
int *N = P;
*N = 20;
}
I think that *P is an lvalue L, &*P is the address &L of L, and P is obviously based on &L. Now if we access the object X using L (*P), then as mentioned in the standard:
then the following requirements apply. Among them, there is one:
Every other lvalue used to access the value of X shall also have its address based on P.
Let’s continue to look at the code. Next, N is assigned the value of P. Then N should also be based on P. Because when P changes, N also needs to change. So this satisfies:
Every other lvalue used to access the value of X shall also have its address based on P.
Then I think that accessing object X via *N is not undefined behavior.
But what I learned before is that,
in each execution of the block where the restrict pointer P is declared, if an object that can be accessed (directly or indirectly) by P is modified by any means, then all accesses to that object in that block must be performed via P; otherwise, the behavior is undefined.
Here I actually used *N (another ordinary pointer) to access the object X, so I am very confused now:
- Is my program strictly in line with the standard (not undefined behavior)?
- If my program is correct, does this mean that the object pointed to by the pointer modified by 'restrict' can be accessed using other ordinary pointers?
- If my program is wrong, then how should we understand the words in the C 2011 standard?