Eric Sosman said:
Personally, I've never been entirely convinced that
`i = f(++i)' is bulletproof. Yes, there's a sequence point
between evaluating `++i' and starting to execute `f', and
there's even another one before `f' returns its value. But
I don't think this guarantees a sequence point between the
evaluation of `++i' and the assignment to the l.h.s.
Now, "it stands to reason" that the assignment cannot
occur until after `f' returns its value, and `f' cannot
return its value until it's been called, so the sequence
point at the call should suffice. But I don't think this
argument is reliable: What if the compiler can predict the
value `f' will return without actually calling it at all?
For example,
int f(int x) {
printf ("%d bottles of beer on the wall\n", x);
return 0; /* 0 = success, -1 = failure */
}
is "predictable," and I think the compiler would be within
its rights to zero `i', call `f', and ignore the returned
value. Lord only knows what would happen to the `++',
or what might appear on stdout. Old Frothingslosh, if
your luck is bad.
The whole purpose of sequence points, I think, is to impose a
reasonable set of of restrictions on what optimizations a compiler is
allowed to perform. An optimizer *can* move a side effect across a
sequence point, but it's allowed to do so only if it doesn't destroy
the semantics of the program. The actual program needs to behave,
within certain limits, in a manner consistent with the way the program
behaves in the C abstract machine.
For example:
int i = 3;
printf("i = %d\n", i);
i ++;
Moving the increment before the printf, causing it to print "i = 4",
would be non-conforming. I believe the transformation you describe
would be non-conforming for the same reasons.
But I'm not 100% certain that I'm correct about this, and I could
probably shoot some holes in my own arguments if I put my mind to it.
As a programmer, I'll just avoid things like "i = f(++i);". If I were
implementing a compiler, I'd try to be conservative enough in my
optimizations so that "i = f(++i);" works as expected, even if I can
justify breaking it by invoking undefined behavior if I squint while
reading the standard.
The real question is, if an implementation does something other than
the obvious for "i = f(++i);", can I complain about non-conformance in
my bug report? I *think* the answer is yes.