Operator precedence and associativity are what decide how operators in an expression are evaluated if there is more than one of them involved. Precedence is about which operators are most tightly bound, and associativity is about whether same precedence operators group from right to left or left to right.
Used together, operator precedence and associativity remove any ambiguity, which means any expression in C++ is well defined in terms of evaluation.
Operators are arranged in terms of priority or precedence. Higher precedence operators are resolved before lower precedence operators are resolved, much like how multiplication and division are resolved before addition and subtraction in the following equation:
// Multiplication is evaluated before addition here
int result{2 + 3 * 4};
Here, * is of a higher precedence than +, so the multiplication of 3 and 4 is resolved first before adding 2 to the result.
The expression is interpreted as:
int result{2 + (3 * 4)};
The result is 14.
If you wanted to force the addition to be done first in terms of evaluation, you'd use parentheses to ensure that happens:
// Use parentheses to override the normal operator precedence
int result{(2 + 3) * 4};
The result is now 20.
Parentheses override the precedence hierarchy.
Certain categories of operators tend to take precedence in general:
Increment and decrement operators, such as
++i,i++,--i, andi--, generally have high precedence levels.Multiplication
*, division/, and modulo or remainder%operators have higher precedence than addition+and subtraction-operators.All relational or comparison operators, such as
<,>,==,!=,>=, and<=, follow in terms of precedence levels after arithmetic operators.Logical AND
&&is processed before logical OR||.Assignment operators, such as
=,+=, and-=, typically have lower precedence so that other expressions can be evaluated before their results are assigned.
These ordering rules help guide the evaluation order when mixed type operators appear. For example, arithmetic operators may be applied before relational operators, and comparison results could then be processed by a logical AND operator before they are assigned to something.
int x{5};
int y{10};
bool flag{true};
// Evaluate the comparisons before applying logical AND
bool result{x < y + 1 && flag};
The expression is interpreted as:
// Require both conditions joined by logical AND to be true
bool result{(x < (y + 1)) && flag};
The addition y + 1 is evaluated first. Its result is then compared with x, and the Boolean result of that comparison is combined with flag.
When multiple operators of the same precedence level appear in an expression, they resolve according to their associativity property.
Most common binary operators associate from left to right:
// Subtraction groups from left to right
int result{10 - 3 - 2};
This means:
int result{(10 - 3) - 2};
The left subtraction is processed first, so the result is 5.
Assignment operators are different and typically associate from right to left:
int a{};
int b{};
int c{};
// Assignment groups from right to left
a = b = c = 10;
This evaluates as:
a = (b = (c = 10));
The rightmost assignment, c = 10, occurs first. The result of that assignment, 10, is then used to evaluate b = 10, and finally that result is used to evaluate a = 10.
This makes it easy to assign one value to several variables.
#include <iostream>
int main()
{
int a{};
int b{};
int c{};
a = b = c = 10;
std::cout << "a = " << a << '\n';
std::cout << "b = " << b << '\n';
std::cout << "c = " << c << '\n';
}
Prefix operators, such as ++x or -y, also usually associate from right to left, although it is more transparent than it sounds when there is just one instance on a line.
Although the compiler will always strictly follow the precedence and associativity rules of C++, it can be much harder for a reader of the code to follow the implicit evaluation order in a complex expression involving multiple types of operators.
Adding parentheses not only reinforces or dictates the evaluation order but greatly improves the clarity and maintainability of the code.
When you are combining arithmetic operations, comparisons, and logical operators in a single statement, it's a good practice to wrap those individual operations in parentheses.
int x{10};
int y{20};
int z{5};
int w{8};
bool result{x < y && z < w};
The expression already works because comparison operators have higher precedence than logical &&. However, parentheses make the two separate comparisons easier to recognize:
bool result{(x < y) && (z < w)};
Both versions have the same meaning, but the second version makes the intended grouping more visible.
#include <iostream>
int main()
{
int first{2 + 3 * 4};
std::cout << "2 + 3 * 4 = " << first << '\n';
int second{(2 + 3) * 4};
std::cout << "(2 + 3) * 4 = " << second << '\n';
int subtraction{20 - 7 - 3};
std::cout << "20 - 7 - 3 = " << subtraction << '\n';
int x{};
int y{};
int z{};
x = y = z = 5;
std::cout << "x = " << x << ", y = " << y << ", z = " << z << '\n';
int p{10};
int q{20};
int r{5};
bool result{p < q && r < p};
std::cout << "p < q && r < p = " << result << '\n';
bool clearer{(p < q) && (r < p)};
std::cout << "(p < q) && (r < p) = " << clearer << '\n';
int number{5};
// Increment the value before the expression uses it
int sum{++number * 2};
std::cout << "++number * 2 = " << sum << ", number = " << number << '\n';
}
Exercise: Operator Precedence and AssociativityStarter code, hints and solutionOpenClose
Practice: Operator Precedence and Associativity
Work through the mission, reveal hints only when needed, and compare your result with the model solution.
Your challenge
Change r to 15 while keeping p and q unchanged. Predict the result of both forms of the AND expression and explain the grouping.
Mission checklist
- Run the starter as a baseline, then predict the change requested in Your challenge.
- Make that change in your editor; use the lesson-specific hints if you need help.
- Compile and run your answer, then compare with the worked solution and explain the result.
Starter program
This is the working baseline, not the completed answer. Compile as C++20, then make the change described above.
#include <iostream>
int main()
{
int first{2 + 3 * 4};
std::cout << "2 + 3 * 4 = " << first << '\n';
int second{(2 + 3) * 4};
std::cout << "(2 + 3) * 4 = " << second << '\n';
int subtraction{20 - 7 - 3};
std::cout << "20 - 7 - 3 = " << subtraction << '\n';
int x{};
int y{};
int z{};
x = y = z = 5;
std::cout << "x = " << x << ", y = " << y << ", z = " << z << '\n';
int p{10};
int q{20};
int r{5};
bool result{p < q && r < p};
std::cout << "p < q && r < p = " << result << '\n';
bool clearer{(p < q) && (r < p)};
std::cout << "(p < q) && (r < p) = " << clearer << '\n';
int number{5};
// Increment the value before the expression uses it
int sum{++number * 2};
std::cout << "++number * 2 = " << sum << ", number = " << number << '\n';
}Hints
Group 2 + 3 * 4 as 2 + (3 * 4), but respect the explicit parentheses in (2 + 3) * 4. Subtraction groups left to right.
In p < q && r < p, evaluate the two comparisons as Boolean operands. Change r so the second comparison becomes false; do not confuse grouping with a general rule about evaluation order.
Worked solution
r is changed from 5 to 15. p < q remains true, but r < p becomes false, so both forms of the AND expression produce 0. The parentheses make the existing grouping explicit; they do not change the result.
#include <iostream>
int main()
{
int first{2 + 3 * 4};
std::cout << "2 + 3 * 4 = " << first << '\n';
int second{(2 + 3) * 4};
std::cout << "(2 + 3) * 4 = " << second << '\n';
int subtraction{20 - 7 - 3};
std::cout << "20 - 7 - 3 = " << subtraction << '\n';
int x{};
int y{};
int z{};
x = y = z = 5;
std::cout << "x = " << x << ", y = " << y << ", z = " << z << '\n';
int p{10};
int q{20};
int r{15};
bool result{p < q && r < p};
std::cout << "p < q && r < p = " << result << '\n';
bool clearer{(p < q) && (r < p)};
std::cout << "(p < q) && (r < p) = " << clearer << '\n';
int number{5};
// Increment the value before the expression uses it
int sum{++number * 2};
std::cout << "++number * 2 = " << sum << ", number = " << number << '\n';
}
Example output
2 + 3 * 4 = 14
(2 + 3) * 4 = 20
20 - 7 - 3 = 10
x = 5, y = 5, z = 5
p < q && r < p = 0
(p < q) && (r < p) = 0
++number * 2 = 12, number = 6
0 comments
No comments yet. Be the first.