[prev] [up] [overview] [next]

Section 4. Expressions

4.1: Why doesn't this code:

	a[i] = i++;

work?

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.

4.2: Under my compiler, the code

	int i = 7;
	printf("%d\n", i++ * i++);

prints 49. Regardless of the order of evaluation, shouldn't it print 56?

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.)

4.3: I've experimented with the code

              int i = 2;
              i = i++;

on several compilers. Some gave i the value 2, some gave 3, but one gave 4. I know the behavior is undefined, but how could it give 4?

Undefined behavior means anything can happen. See question 5.23.

4.4: People keep saying the behavior is undefined, but I just tried it on an ANSI-conforming compiler, and got the results I expected.

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.

4.5: Can I use explicit parentheses to force the order of evaluation I want? Even if I don't, doesn't precedence dictate it?

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.

4.6: But what about the &&, ||, and comma operators? I see code like "if((c = getchar()) == EOF || c == '\n')" ...

There is a special exception for those operators, (as well as ?:); 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.

4.7: If I'm not using the value of the expression, should I use 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.

4.8: Why doesn't the code

	int a = 1000, b = 1000;
	long int c = a * b;

work?

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;


[prev] [up] [overview] [next]