Could someone give me the name of a compiler/environment where this code
[below] evaluates left to right (or, at least not right to left!) ...
all the gcc implentations I have to hand does this right to left.
So, I'd like to give a concrete counter example.
#include <stdio.h>
int main(void)
{
int n = 1;
/* They'd like this to result in 1, 10, 100.
*/
printf("%d %d %d", n, n *= 10, n *= 10);
return 0;
}
Indeed, as everyone else has noted, this results in undefined
behavior. The question, however, is whether someone has an example
system on which (a) output is produced, and (b) the output is
"1 10 100". (It would help to add a newline.)
The old Pyramid C compiler would have done that, as it evaluated
the first 12 arguments left-to-right. Arguments beyond the first
twelve were evaluated right-to-left (and before the first twelve
were handled left-to-right). This was because most parameters are
passed in the Parameter Registers, pr0 through pr11 inclusive,
while those that do not fit are passed on a conventional stack.
(In the callee, the registers are named pr0 through pr11 -- the
caller addresses them as tr0 through tr11, the temporary or transfer
registers. Normally these are available for scratch computations.
Return values go in pr0 so that the caller sees them in tr0.)
It is generally difficult to find compilers that work strictly
L-to-R: good compilers often seem to do the evaluation in "apparently
random order", while poor compilers usually do them in whatever
order is easiest on the target hardware, and common target hardware
happens to cause the latter to be R-to-L.
Presumably the reason for the desire for "1 10 100" output is to
demonstrate that not all compilers produce "100 10 1", in an effort
to convince programmers that they should avoid such code. But
those who will not be convinced by the text of the C Standards
might also not be convinced by counterexamples: "Why, those compilers
are just broken," they might say.
Still, one handy counterexample I have is a Mac G4 (PowerPC) running
OS X 10.2 (one of these days I should upgrade it). After fixing
the code above to include a terminating newline, and compiling with
"cc" (which is Apple GCC version 1175 "based on gcc version 3.1
20020420 (prerelease)"), I get:
% cc -o t t.c
% ./t
100 10 100
The output remains unchanged when optimized (with -O or -O2).
The PowerPC, MIPS, and SPARC are three good architectures to
try, as all three generally use registers for parameter-passing.
Note that calling a function other than printf() might change the
result on some machines, because printf() is a variable-argument
function, and there are good reasons to want to use different
calling conventions for fixed vs variable argument functions.