Operator Precedence and Associativity

Two operator characteristics determine how operands group with operators: precedence and associativity. Precedence is the priority for grouping different types of operators with their operands. Associativity is the left-to-right or right-to-left order for grouping operands to operators that have the same precedence. An operator's precedence is meaningful only if other operators with higher or lower precedence are present. Expressions with higher-precedence operators are evaluated first. The grouping of operands can be forced by using parentheses.

For example, in the following statements, the value of 5 is assigned to both a and b because of the right-to-left associativity of the = operator. The value of c is assigned to b first, and then the value of b is assigned to a.

b = 9;
c = 5;
a = b = c;

Because the order of subexpression evaluation is not specified, you can explicitly force the grouping of operands with operators by using parentheses.

In the expression

a + b * c / d

the * and / operations are performed before + because of precedence. b is multiplied by c before it is divided by d because of associativity.

The following table lists the C and C++ language operators in order of precedence and shows the direction of associativity for each operator.

The C++ scope resolution operator (::) has the highest precedence. The comma operator has the lowest precedence. Operators that have the same rank have the same precedence.

Precedence and associativity of C and C++ operators
Rank Right Associative? Operator Function Usage
1 yes C++ global scope resolution
:: name_or_qualified name
1
C++ class or namespace scope resolution
class_or_namespace :: member
2
member selection object . member
2
member selection pointer -> member
2
subscripting pointer [ expr ]
2
function call expr ( expr_list )
2
value construction type ( expr_list )
2
postfix increment lvalue ++
2
postfix decrement lvalue --
2 yes C++ type identification
typeid ( type )
2 yes C++ type identification at run time
typeid ( expr )
2 yes C++ conversion checked at compile time
static_cast < type > ( expr )
2 yes C++ conversion checked at run time
dynamic_cast < type > ( expr )
2 yes C++ unchecked conversion
reinterpret_cast < type > ( expr )
2 yes C++const conversion
const_cast < type > ( expr )
3 yes size of object in bytes sizeof expr
3 yes size of type in bytes sizeof ( type )
3 yes prefix increment ++ lvalue
3 yes prefix decrement -- lvalue
3 yes bitwise negation ~ expr
3 yes not ! expr
3 yes unary minus - expr
3 yes unary plus + expr
3 yes address of & lvalue
3 yes indirection or dereference * expr
3 yes C++create (allocate memory)
new type
3 yes C++create (allocate and initialize memory)
new type ( expr_list ) type
3 yes C++create (placement)
new type ( expr_list ) type ( expr_list )
3 yes C++destroy (deallocate memory)
delete pointer
3 yes C++destroy array
delete [ ] pointer
3 yes type conversion (cast) ( type ) expr
4
member selection object .* ptr_to_member
4
member selection object ->* ptr_to_member
5
multiplication expr * expr
5
division expr / expr
5
modulo (remainder) expr % expr
6
binary addition expr + expr
6
binary subtraction expr - expr
7
bitwise shift left expr << expr
7
bitwise shift right expr >> expr
8
less than expr < expr
8
less than or equal to expr <= expr
8
greater than expr > expr
8
greater than or equal to expr >= expr
9
equal expr == expr
9
not equal expr != expr
10
bitwise AND expr & expr
11
bitwise exclusive OR expr ^ expr
12
bitwise inclusive OR expr | expr
13
logical AND expr && expr
14
logical inclusive OR expr || expr
15
conditional expression expr ? expr : expr
16 yes simple assignment lvalue = expr
16 yes multiply and assign lvalue *= expr
16 yes divide and assign lvalue /= expr
16 yes modulo and assign lvalue %= expr
16 yes add and assign lvalue += expr
16 yes subtract and assign lvalue -= expr
16 yes shift left and assign lvalue <<= expr
16 yes shift right and assign lvalue >>= expr
16 yes bitwise AND and assign lvalue &= expr
16 yes bitwise exclusive OR and assign lvalue ^= expr
16 yes bitwise inclusive OR and assign lvalue |= expr
17 yes C++throw expression
throw expr
18
comma (sequencing) expr , expr

The order of evaluation for function call arguments or for the operands of binary operators is not specified. Avoid writing ambiguous expressions such as:

z = (x * ++y) / func1(y);
func2(++i, x[i]);

In the example above, ++y and func1(y) might not be evaluated in the same order by all C language implementations. If y has the value of 1 before the first statement, it is not known whether or not the value of 1 or 2 is passed to func1(). In the second statement, if i has the value of 1 before the expression is evaluated, it is not known whether x[1] or x[2] is passed as the second argument to func2().

Related References

IBM Copyright 2003