Reputation: 12638
When using a restrict
Pointer in C, is it OK to change the variable using its initial Identifier? For example:
int foo = 0;
int * restrict fooPtr = &foo;
++(*fooPtr); // Part 1: foo is 1 (OK)
++foo; // Part 2: foo is 2 (Is this OK?)
int * fooPtr2 = &foo;
++(*fooPtr2); // Part 3: foo is 3 (BAD: You shouldn't access via a second pointer)
...I changed the value of foo through foo after the restrict
fooPtr was created.
Part 1 looks OK to me. I'm confused about Part 2. And from what I understand about restrict
, Part 3 is bad (compiler allows it, but its behavior is undefined, and it's up to the programmer not to do that).
Upvotes: 4
Views: 813
Reputation: 279255
No, Part 2 is not OK.
The specific part of the standard is 6.7.3.1/4. This section is pretty dense, and takes a few re-reads, but P is a restrict pointer, and X is some object it is used to access, and which is modified. So in your example P is fooPtr
and X is foo
. Then:
Every other lvalue used to access the value of X shall also have its address based on P.
"based on" is defined in the previous paragraph, and to summarize, the lvalue foo
does not have its address based on the restrict pointer P. So the rule is broken when you access the object foo
through its own name.
Part 3 is not OK for exactly the same reason, the lvalue *fooPtr2
isn't based on P either, but is also used to access X.
I say "not OK" - to be precise, the combination of 1+2 provokes undefined behavior, as does the combination of 1+3. As long as you don't actually access the object through the restrict pointer, none of the definition of restrict "kicks in". If you wanted to you could remove Part 1, retain the unused restrict pointer, and then 2 and 3 would be OK.
Upvotes: 4
Reputation: 340218
Assuming that all of the parts of your question occur in the same block, it's not OK to access the value of foo
directly (part 2) nor to access it via another pointer (part 3):
Every other lvalue used to access the value of X shall also have its address based on P.
The formal definition of restrict
is quite difficult to follow (at least it is for me), however the following less formal description also from the standard sums it up pretty well (at least for this case):
An object that is accessed through a restrict-qualified pointer has a special association with that pointer. This association, defined in 6.7.3.1 below, requires that all accesses to that object use, directly or indirectly, the value of that particular pointer.
Upvotes: 1
Reputation: 1054
I'd say #2 is bad. For instance, the compiler might optimize by loading the value at *fooPtr into a register, and then write that register value back out to foo again later - after your ++foo, so that the ++foo is lost.
Upvotes: 1
Reputation: 272517
Yes, "part 3" is undefined behaviour. From the C99 spec (6.7.3, paragraph 7):
An object that is accessed through a restrict-qualified pointer has a special association with that pointer. This association, defined in 6.7.3.1 below, requires that all accesses to that object use, directly or indirectly, the value of that particular pointer.
Upvotes: 1