Order of Evaluation

This section discusses the order in which expressions are evaluated but does not explain the syntax or the semantics of the operators in these expressions. The earlier sections in this chapter provide a complete reference for each of these operators.

Expressions are evaluated according to the precedence and grouping of their operators. (Table 1.2 in Chapter 1, “Lexical Conventions,” shows the relationships the C++ operators impose on expressions.) Consider this example:

#include <iostream.h>

int main()

{

int a = 2, b = 4, c = 9;

cout << a + b * c << “\n”;

cout << a + (b * c) << “\n”;

cout << (a + b) * c << “\n”;

return 0;

}

The output from the above code is:

38

38

54

Figure 4.1 shows the order in which the expressions are evaluated.

The order in which the expression shown in Figure 4.1 is evaluated is determined by the precedence and associativity of the operators:

1.Multiplication (*) has the highest precedence in this expression; hence the subexpression b * c is evaluated first.

2.Addition (+) has the next highest precedence, so a is added to the product of b and c.

3.Left shift (<<) has the lowest precedence in the expression, but there are two occurrences. Because the left-shift operator groups left-to-right, the left subexpression is evaluated, then the right one.

When parentheses are used to group the subexpressions, they alter the precedence and also the order in which the expression is evaluated, as shown in Figure 4.2.

Expressions such as those shown in Figure 4.2 are evaluated purely for their side effects—in this case, to transfer information to the standard output device.

Note:

The left-shift operator is used to insert an object in an object of class ostream. It is sometimes called the “insertion” operator when used with iostream. For more about the iostream library, see Chapters 18 and 19 of the Class Libraries User's Guide manual and Part 3 of the Class Libraries Reference manual.

Sequence Points

An expression can modify an object's value only once between consecutive “sequence points.”

Microsoft Specific

The C++ language definition does not currently specify sequence points, Microsoft C++ uses the same sequence points as ANSI C for any expression involving C operators and not involving overloaded operators. When operators are overloaded, the semantics change from operator sequencing to function-call sequencing. Microsoft C++ uses the following sequence points:

Left operand of the logical AND operator. The left operand of the logical AND operator is completely evaluated and all side effects completed before continuing. There is no guarantee that the right operand of the logical AND operator will be evaluated.

Left operand of the logical OR operator. The left operand of the logical OR operator is completely evaluated and all side effects completed before continuing. There is no guarantee that the right operand of the logical OR operator will be evaluated.

Left operand of the comma operator. The left operand of the comma operator is completely evaluated and all side effects completed before continuing. Both operands of the comma operator are always evaluated.

Function-call operator. All arguments to a function, including default arguments, are evaluated and all side effects completed prior to entry to the function. No order of evaluation among the arguments or the function-call expression is specified.

First operand of the conditional operator. The first operand of the conditional operator is completely evaluated and all side effects completed before continuing.

The end of a full initialization expression.

The expression in an expression statement. Expression statements consist of an optional expression followed by a semicolon (;). The expression is completely evaluated for its side effects.

The controlling expression in a selection (if or switch) statement. The expression is completely evaluated and all side effects completed before the code dependent on the selection is executed.

The controlling expression of a while or do statement. The expression is completely evaluated and all side effects completed before any statements in the next iteration of the while or do loop are executed.

Each of the three expressions of a for statement. Each expression is completely evaluated and all side effects completed before moving to the next expression. The three expressions are (collectively) completely evaluated and all side effects completed before any statements in the next iteration of the for loop are executed.

The expression in a return statement. The expression is completely evaluated and all side effects completed before control returns to the calling function. ¨

Gray Expressions

Certain expressions, called “gray expressions,” are ambiguous in their meaning. These expressions occur most frequently when an object's value is modified more than once in the same expression. Gray expressions rely on a particular order of evaluation where the language does not define one. Consider the following example:

int i = 7;

func( i, ++i );

The C++ language does not guarantee in which order the arguments to a function call are evaluated. Therefore, in the example above, func could receive the values 7 and 8, or 8 and 8 for its parameters, depending on whether the parameters are evaluated from left to right or from right to left.