4.1.2. Precedence and Associativity

Image

An expression with two or more operators is a compound expression. Evaluating a compound expression involves grouping the operands to the operators. Precedence and associativity determine how the operands are grouped. That is, they determine which parts of the expression are the operands for each of the operators in the expression. Programmers can override these rules by parenthesizing compound expressions to force a particular grouping.

In general, the value of an expression depends on how the subexpressions are grouped. Operands of operators with higher precedence group more tightly than operands of operators at lower precedence. Associativity determines how to group operands with the same precedence. For example, multiplication and division have the same precedence as each other, but they have higher precedence than addition. Therefore, operands to multiplication and division group before operands to addition and subtraction. The arithmetic operators are left associative, which means operators at the same precdence group left to right:

• Because of precedence, the expression 3+4*5 is 23, not 35.

• Because of associativity, the expression 20-15-3 is 2, not 8.

As a more complicated example, a left-to-right evaluation of the following expression yields 20:

6 + 3 * 4 / 2 + 2

Other imaginable results include 9, 14, and 36. In C++, the result is 14, because this expression is equivalent to

// parentheses in this expression match default precedence and associativity
((6 + ((3 * 4) / 2)) + 2)

Parentheses Override Precedence and Associativity

We can override the normal grouping with parentheses. Parenthesized expressions are evaluated by treating each parenthesized subexpression as a unit and otherwise applying the normal precedence rules. For example, we can parenthesize the expression above to force the result to be any of the four possible values:

// parentheses result in alternative groupings
cout << (6 + 3) *  (4 / 2 + 2) << endl;    // prints 36
cout << ((6 + 3) *  4) / 2 + 2 << endl;    // prints 20
cout << 6 + 3 * 4  / (2 + 2) << endl;      // prints 9

When Precedence and Associativity Matter
Image

We have already seen examples where precedence affects the correctness of our programs. For example, consider the discussion in § 3.5.3 (p. 120) about dereference and pointer arithmetic:

int ia[] = {0,2,4,6,8}; // array with five elements of type int
int last = *(ia + 4);   // initializes last to 8, the value of ia [4]
last = *ia + 4;          // last = 4, equivalent to ia [0] + 4

If we want to access the element at the location ia+4, then the parentheses around the addition are essential. Without parentheses, *ia is grouped first and 4 is added to the value in *ia.

The most common case that we’ve seen in which associativity matters is in input and output expressions. As we’ll see in § 4.8 (p. 155), the operators used for IO are left associative. This associativity means we can combine several IO operations in a single expression:

cin >> v1 >> v2; // read into v1 and then into v2

Table 4.12 (p. 166) lists all the operators organized into segments separated by double lines. Operators in each segment have the same precedence, and have higher precedence than operators in subsequent segments. For example, the prefix increment and dereference operators share the same precedence, which is higher than that of the arithmetic operators. The table includes a page reference to each operator’s description. We have seen some of these operators already and will cover most of the rest in this chapter. However, there are a few operators that we will not cover until later.


Exercises Section 4.1.2

Exercise 4.1: What is the value returned by 5 + 10 * 20/2?

Exercise 4.2: Using Table 4.12 (p. 166), parenthesize the following expressions to indicate the order in which the operands are grouped:

(a) * vec.begin()

(b) * vec.begin() + 1


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.78.102