user3020134
user3020134

Reputation: 21

Consecutive pointer assignment with post-increment

I came across this piece of code in C:

*p++=*q++=*r++;

In my opinion it's erroneous because I can't recall any rule in C specifying when the ++ after q should be actually conducted - before the assignment between *p++ and *q++, or after?

Therefore my impression is that this may very likely be an undefined behavior, but could not pinpoint where exactly in the C standards (C89 or C99) this is accounted for.

This is where help from language cops is really appreciated. Please shed light.

Upvotes: 2

Views: 895

Answers (4)

AnT stands with Russia
AnT stands with Russia

Reputation: 320719

The behavior of this code does not depend at all on when the ++ is physically carried out. The behavior is well-defined.

The fact that the postfix form of increment is used simply means that the original values of pointers are used as results of increment. I.e. the whole thing is equivalent to

old_p = p;
old_q = q;
old_r = r;

*old_p = *old_q = *old_r;

p = p + 1;
q = q + 1;
r = r + 1;

Note that you can freely move the physical increments around in completely arbitrary fashion, as in

old_p = p;
old_q = q;
old_r = r;

p = p + 1;
q = q + 1;

*old_p = *old_q = *old_r;

r = r + 1;

The semantics of the code does not change, as long as the original pointer values are used in the assignment.

Also note that the original value does have to be stored to be available in assignment. The compiler is free to recover that original value by re-evaluating it through decrement. I.e. the compiler can even translate your expression into something like

p = p + 1;
q = q + 1;

*(p - 1) = *(q - 1) = *r;

r = r + 1;

Upvotes: 4

Shafik Yaghmour
Shafik Yaghmour

Reputation: 158599

Assignment has lower precedence than both * and ++(both post and pre) so assignment will happen afterwards but the order of evaluation of the operands to = is unspecified which should not matter in this case unless r, p or q point to the same location in which case you would have undefined behavior anyway since you would be modifying the same object more than once within the same sequence point.

The C99 draft standard section 6.5.16 Assignment operators paragraph 3 says:

[...]The side effect of updating the stored value of the left operand shall occur between the previous and the next sequence point.[...]

and paragraph 4 says:

The order of evaluation of the operands is unspecified. [...]

Upvotes: 1

Jonathan Leffler
Jonathan Leffler

Reputation: 754860

Since you are incrementing three different pointer variables, the overall behaviour is perfectly well defined (assuming the pointers all point to valid storage locations). It is not specified whether the increment of r takes place before or after the assignment to p, but that doesn't affect the result, either.

For convenience, suppose we have:

char buffer1[10];
char buffer2[10];
char buffer3[] = "abc";
char *p = buffer1;
char *q = buffer2;
char *r = buffer3;

*p++ = *q++ = *r++;

After this has executed, all of these assertions are safe:

assert(p == buffer1 + 1);  // Or p == &buffer1[1];
assert(q == buffer2 + 1);  // Or q == &buffer2[1];
assert(r == buffer3 + 1);  // Or r == &buffer3[1];
assert(*r == 'b');
assert(buffer1[0] == 'a');
assert(buffer2[0] == 'a');

Upvotes: 2

zen
zen

Reputation: 357

If I am not mistaken, post-increment is always performed at the end of the assignment

i.e

increment in *r

*q<-*r

increment in *q

*p<-*q

increment in *p

"It is important to note that a postfix increment or decrement expression evaluates to the value of the expression prior to application of the respective operator."

Upvotes: 0

Related Questions