a[i] = i++;
The subexpression i++
causes a side effect -- it modifies i
's
value -- which leads to undefined behavior if i
is also
referenced elsewhere in the same expression. (Note that
although the language in K&R suggests that the behavior of this
expression is unspecified, the ANSI/ISO C Standard makes the
stronger statement that it is undefined -- see question 5.23.)
References: ANSI Sec. 3.3 p. 39.
int i = 7; printf("%d\n", i++ * i++);
Although the postincrement and postdecrement operators ++
and --
perform the operations after yielding the former value, the
implication of "after" is often misunderstood. It is not
guaranteed that the operation is performed immediately after
giving up the previous value and before any other part of the
expression is evaluated. It is merely guaranteed that the
update will be performed sometime before the expression is
considered "finished" (before the next "sequence point," in ANSI
C's terminology). In the example, the compiler chose to
multiply the previous value by itself and to perform both
increments afterwards.
The behavior of code which contains multiple, ambiguous side effects has always been undefined (see question 5.23). Don't even try to find out how your compiler implements such things (contrary to the ill-advised exercises in many C textbooks); as K&R wisely point out, "if you don't know how they are done on various machines, that innocence may help to protect you."
References: K&R I Sec. 2.12 p. 50; K&R II Sec. 2.12 p. 54; ANSI Sec. 3.3 p. 39; CT&P Sec. 3.7 p. 47; PCS Sec. 9.5 pp. 120-1. (Ignore H&S Sec. 7.12 pp. 190-1, which is obsolete.)
int i = 2; i = i++;
Undefined behavior means anything can happen. See question 5.23.
A compiler may do anything it likes when faced with undefined behavior (and, within limits, with implementation-defined and unspecified behavior), including doing what you expect. It's unwise to depend on it, though. See also question 5.18.
Operator precedence and explicit parentheses impose only a partial ordering on the evaluation of an expression. Consider the expression
f() + g() * h()-- although we know that the multiplication will happen before the addition, there is no telling which of the three functions will be called first.
&&,
||,
and comma operators?
I see code like "if((c = getchar()) == EOF || c == '\n')
" ...
There is a special exception for those operators, (as well as the ?:
operator); each of them does imply a sequence point (i.e. left-to-right evaluation is guaranteed). Any book on C should make this
clear.
References: K&R I Sec. 2.6 p. 38, Secs. A7.11-12 pp. 190-1; K&R II Sec. 2.6 p. 41, Secs. A7.14-15 pp. 207-8; ANSI Secs. 3.3.13 p. 52, 3.3.14 p. 52, 3.3.15 p. 53, 3.3.17 p. 55, CT&P Sec. 3.7 pp. 46-7.
i++
or ++i
to increment a variable?
Since the two forms differ only in the value yielded, they are entirely equivalent when only their side effect is needed.
int a = 1000, b = 1000; long int c = a * b;
Under C's integral promotion rules, the multiplication is
carried out using int
arithmetic, and the result may overflow
and/or be truncated before being assigned to the long int
left-
hand-side. Use an explicit cast to force long
arithmetic:
long int c = (long int)a * b;Note that the code
(long int)(a * b)
would not
have the desired effect.