Previous Table of Contents Next


3.3.6. Compound Assignment Operators

Patterns of the form

i = i + 1

turn up frequently in programming. C provides 10 shorthand assignment operators to simplify these patterns. Any expression of the form v = v op e, where op is one of the binary operators +, -, *, /, %, &, |, ^, <<, or >>, can be replaced with v op= e. Thus, i += 1 is equivalent to i = i + 1 and increments i by 1, j -= 2 decrements j by 2, x *= 10 multiplies x by 10 (in place), and y %= 10 replaces y by its remainder when divided by 10. These assignment operators are particularly useful when the expression designating the object being modified is more complicated; for example,

tab[a + b + 2*c + d[e]] += 1

is clearly easier to write, read, and verify as correct than the longhand form

tab[a + b + 2*c + d[e]] = tab[a + b + 2*c + d[e]] + 1

Moreover, in the form using the assignment operator, the expression designating the object being modified is evaluated only once (which is natural because it appears only once). For example, in the slightly modified example

tab[a + b + 2*c + f(e)] += 1

the function f() is called only once. The assignment forms of the bitwise operators are also commonly seen; for example, the operations of setting, clearing, and toggling a bit can be succinctly expressed as flags |= 0x10, flags &= ~0x10, and flags ^= 0x10.

As was the case for the simple assignment operator =, expressions involving the compound assignment operators all yield values, namely the new values assigned to the left-hand side.

3.3.7. Autoincrement and Autodecrement Operators

C has two more shorthand increment and decrement operators. The assignment operators of the preceding section allow the general expression a = b op c to be simplified when a and b are identical, but these two operators allow a further simplification when op is + or - and c is 1. The expression ++v is equivalent to v = v + 1 (and, hence, to v += 1), and the expression --v is equivalent to v = v - 1.

Like all expressions in C, expressions involving ++ and -- yield values and can be used as subexpressions within larger expressions. The value of the expression ++i is the incremented value of i (as would be expected based on examination of the equivalent forms i += 1 and i = i + 1). However, the ++ and -- operators can also be used in two alternative forms, with significantly different results. Used as postfixed unary operators, as in i++ and j--, the value yielded to the surrounding expression (if any) is the old value, before the increment or decrement. Thus, the statement

a[i++] = 0;

is equivalent to the two statements

a[i] = 0;
i = i + 1;

and the statement

b[++i] = 0;

is equivalent to the two statements

i = i + 1;
b[i] = 0;

The only difference between the prefix and postfix forms is the value given up to the surrounding expression. Therefore, when there is no surrounding expression (when an expression involving ++ or -- stands alone, as in i++;), it makes no difference which form is used.

Because they modify the stored values of their operands, we say that the increment and decrement operators, too, produce side effects. Not only does the expression ++i generate the value i+1 for use in a surrounding expression, it also assigns this new value back to i. Thus, it is unnecessary (and, in fact, utterly incorrect) to write

i = ++i;          /* WRONG */

The expression ++i all by itself is sufficient to assign the incremented value back to i. To increment i using an assignment operator, use i = i + 1 or i += 1. See section 3.3.9 for additional caveats concerning ++ and other operators with side effects.

3.3.8. Conditional and Comma Operators

Two more operators that don’t fit into any of the preceding categories are the conditional and comma operators. The conditional operator (which is a ternary operator, because unlike unary and binary operators, it takes three operands) is essentially an if/else statement buried in an expression. The expression c ? a : b has the value a if the condition c evaluates to nonzero (i.e., true), and the value b if c evaluates to 0. For example, the expression

m = (r > 0) ? a + 1 : b - 1

is equivalent to the code

if(r > 0)
          m = a + 1;
else      m = b - 1;

The expression

a > b ? a : b

computes the maximum of a and b.

The conditional operator always evaluates its first operand (the conditional subexpression) first, and evaluates only one of its second and third operands as appropriate. Like the && and || operators, it can therefore be safely used when the order of evaluation is important and must be constrained. For example, the expression

avg = (n > 0) ? sum / n : 0

does not divide by 0 even if n is 0.

The comma operator evaluates two subexpressions, discarding the value of the first one and returning the value of the second. For example, the expression

a = 1, b = 2

assigns 1 to a and then assigns 2 to b. The final value of the expression is 2.

The comma operator is used where two expressions must be evaluated in sequence in a context in which (syntactically) one expression is expected. Its only common use is in the first or third controlling expression of a for loop (see section 3.4.5).

Note that the commas which separate the arguments in a function call are not comma operators. (Among other things, the commas in a function call do not impose a defined order of evaluation.)


Previous Table of Contents Next