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 |
![]() | :: name_or_qualified name |
1 |
|
![]() | 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 |
![]() | typeid ( type ) |
2 | yes |
![]() | typeid ( expr ) |
2 | yes |
![]() | static_cast < type > ( expr ) |
2 | yes |
![]() | dynamic_cast < type > ( expr ) |
2 | yes |
![]() | reinterpret_cast < type > ( expr ) |
2 | yes |
![]() | 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 |
![]() | new type |
3 | yes |
![]() | new type ( expr_list ) type |
3 | yes |
![]() | new type ( expr_list ) type ( expr_list ) |
3 | yes |
![]() | delete pointer |
3 | yes |
![]() | 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 |
![]() | 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