The order in which function arguments
are evaluated is not specified, so the
statement
printf("%d %d\n", ++n, power(2, n)); /* WRONG */
can produce different results with
different compilers, depending on
whether n is incremented before power
is called. The solution, of course, is
to write
++n;
printf("%d %d\n", n, power(2, n));
Function calls, nested assignment
statements, and increment and
decrement operators cause ``side
effects'' - some variable is changed
as a by-product of the evaluation of
an expression. In any expression
involving side effects, there can be
subtle dependencies on the order in
which variables taking part in the
expression are updated. One unhappy
situation is typified by the statement
a[i] = i++
The question is whether the subscript
is the old value of i or the new.
Compilers can interpret this in
different ways, and generate different
answers depending on their
interpretation. The standard
intentionally leaves most such matters
unspecified. When side effects
(assignment to variables) take place
within an expression is left to the
discretion of the compiler, since the
best order depends strongly on machine
architecture. (The standard does
specify that all side effects on
arguments take effect before a
function is called, but that would not
help in the call to printf above.) The
moral is that writing code that
depends on order of evaluation is a
bad programming practice in any
language. Naturally, it is necessary
to know what things to avoid, but if
you don't know how they are done on
various machines, you won't be tempted
to take advantage of a particular
implementation.