Possible Duplicate:
Undefined Behavior and Sequence Points
As defined in the standard, E1 += E2 is almost same to E1 = E1 + E2 except that E1 is only evaluated once. So, in addition, would “p += (*p)++ + c”; cause an undefined behavior?
Try the following code in gcc/g++ (4.7 / 4.4). There are 2 kind of results: bxxxxx (g++4.7) or axbxxx (gcc, g++ 4.4). If we’re executing (1) but not (2) in the code, we can only get axbxxx.
#include <stdio.h>
int main() {
char s[] = "axxxxx";
char *p = s;
printf("s = %s in the beginning.\n"
"p is pointed at the %d-th char.\n", s, p - s);
//p = p + (*p)++ * 3 + 2 - 'a' * 3; // (1)
p += (*p)++ * 3 + 2 - 'a' * 3; // (2)
printf("p is moved ahead by %d steps\n", p - s);
printf("s = %s after the operation.\n", s);
return 0;
}
I can’t find why it cause undefined behavior, nor can I assert that it’s a bug of gcc.
For the axbxxx result, I also can’t understand why a operand or post ++ is evaluated twice (once getting the value, and later saving it). Since in the standard says “1 … is added to it”, I think the address should only be evaluated once. If the address of the operand of the post ++ is evaluated only once, the effect of the expression will be the same despite in whatever order the assignments are executed.
=== UPDATE ===
After reading the document linked in the first comment, I think the following rule may matter:
“2) Furthermore, the prior value shall be accessed only to determine the value to be stored.” .
So, would the access of p in “p = p + (*p)++ * 3 + c” be considered a part of “prior value” of *p which has nothing to do with the value to be stored in *p?
IMO, this rule is not violated.
No,
p = p + (*p)++ * 3 + cdoesn’t cause any undefined behavior, assuming thatpdoes not point atc.In this case the questionable part is the read and modification of the value of
*pinside the expression. However, that value is read for the purpose of determining the new value ofp(there’s a straightforward data dependency of the new value ofpon the value read in*p), so it does not violate the requirements.I’d guess that the bug in the compiler is actually rooted in its incorrect behavior in an unspecified situation. Note that the expression has two side-effects: store the new value in
pand store the new value in*p. It is unspecified in which order these side-effects occur. However, during the evaluation of the(*p)++subexpression the compiler was supposed to “fix” the specific lvalue argument of++to make sure that the new (incremented) value was stored in that exact object. It looks like the older version of the compiler failed to do that, i.e. the new value ofpis evaluated first and then the new value of*pis stored through the new value ofp. This is obviously incorrect.