C Operator Precedence
Updated 6 min read Aimerscrew
What does 4 + 6 * 2 - 8 / 4 equal in C? If you said 14, you already know the most important rule. C operator precedence is the set of rules that decides which operator in an expression goes first. In this lesson, you'll see the full ranking of C's operators, learn what associativity means, watch an expression being evaluated step by step, and learn the traps that catch even experienced programmers.
🌍 Real-life example
At a café you order 3 coffees at $4 each, plus a $5 sandwich. Everyone knows the bill is 3 × 4 + 5 = $17, not 3 × (4 + 5) = $27, because you multiply before you add. C follows the same school-math habit, and then adds rules for its many extra operators like &&, == and =.
What is operator precedence in C?
Precedence is the priority of an operator. When an expression contains several operators, those with higher precedence are grouped with their operands first. Because * has higher precedence than +, C reads 2 + 3 * 4 as 2 + (3 * 4).
Associativity is the tie-breaker. When two operators have the same precedence, associativity says whether to group from left to right or right to left. Most operators are left to right: 10 - 4 - 3 is (10 - 4) - 3, which is 3, not 9.
#include <stdio.h>
int main(void) {
int a = 2 + 3 * 4;
int b = (2 + 3) * 4;
int c = 10 - 4 - 3;
int d = 20 / 2 * 5;
int e = 17 % 5 * 2;
printf("2 + 3 * 4 = %d\n", a);
printf("(2 + 3) * 4 = %d\n", b);
printf("10 - 4 - 3 = %d\n", c);
printf("20 / 2 * 5 = %d\n", d);
printf("17 %% 5 * 2 = %d\n", e);
return 0;
}
2 + 3 * 4 = 14
(2 + 3) * 4 = 20
10 - 4 - 3 = 3
20 / 2 * 5 = 50
17 % 5 * 2 = 4
Look at 20 / 2 * 5: / and * share the same level, so C goes left to right: 20 / 2 is 10, then 10 * 5 is 50.
C operator precedence table
Here are C's operators from highest precedence (applied first) to lowest. Operators in the same row share a level.
| Level | Operators | Description | Associativity |
|---|---|---|---|
| 1 | () [] -> . x++ x-- | function call, array index, member access, postfix | left to right |
| 2 | ++x --x + - ! ~ * & sizeof (type) | prefix, unary plus/minus, NOT, dereference, address-of, cast | right to left |
| 3 | * / % | multiply, divide, remainder | left to right |
| 4 | + - | add, subtract | left to right |
| 5 | << >> | bit shifts | left to right |
| 6 | < <= > >= | relational comparisons | left to right |
| 7 | == != | equality | left to right |
| 8 | & | bitwise AND | left to right |
| 9 | ^ | bitwise XOR | left to right |
| 10 | | | bitwise OR | left to right |
| 11 | && | logical AND | left to right |
| 12 | || | logical OR | left to right |
| 13 | ?: | conditional (ternary) | right to left |
| 14 | = += -= *= /= %= &= |= ^= <<= >>= | assignment | right to left |
| 15 | , | comma | left to right |
You don't need to memorize all of it. A rough order is enough for daily work: unary → arithmetic → shifts → comparisons → bitwise → logical → ternary → assignment. A few operators in the table, like ->, unary * and &, belong to pointers and structs, and ?: is covered in the ternary operator lesson.
Evaluating an expression step by step
Let's work through 4 + 6 * 2 - 8 / 4 the way C groups it. At each step, find the highest-precedence operator; if there's a tie, take the leftmost one.
#include <stdio.h>
int main(void) {
int total = 4 + 6 * 2 - 8 / 4;
printf("total = %d\n", total);
return 0;
}
total = 14
Right-to-left associativity
Unary operators, the ternary operator and all assignment operators group right to left. That's what makes chained assignment work: x = y = z = 7 means x = (y = (z = 7)).
#include <stdio.h>
int main(void) {
int x, y, z;
x = y = z = 7;
printf("%d %d %d\n", x, y, z);
int n = 5;
printf("-n * 2 = %d\n", -n * 2);
return 0;
}
7 7 7
-n * 2 = -10
Unary minus is level 2, higher than *, so -n * 2 is (-n) * 2.
How operators mix in a real expression
Because arithmetic comes before comparisons, and comparisons before &&, and assignment comes last, many everyday expressions just work without parentheses:
#include <stdio.h>
int main(void) {
int price = 25;
int quantity = 3;
int shipping = 5;
int budget = 80;
int total = price * quantity + shipping;
int within_budget = total <= budget && quantity > 0;
int discounted = total * (100 - 20) / 100;
printf("Total: $%d\n", total);
printf("Within budget: %d\n", within_budget);
printf("With 20%% off: $%d\n", discounted);
return 0;
}
Total: $80
Within budget: 1
With 20% off: $64
In total <= budget && quantity > 0, the two comparisons run first (giving 1 and 1), then && combines them, and finally = stores the result. The parentheses in (100 - 20) are required: without them, C would compute total * 100 - 20 / 100.
When should you use parentheses?
Parentheses have the highest priority of all, so they always win. Use them whenever:
- you need a different order than the default, like
(a + b) / 2; - you mix
&&and||, or bitwise operators with comparisons; - a reader would have to look up the table to be sure.
Extra parentheses cost nothing at run time. Code is read far more often than it is written, so clarity wins.
💡 Tip
Compile with -Wall. GCC's -Wparentheses warning (part of -Wall) catches several of the traps below and suggests where to add parentheses.
📝 Note
Precedence decides how an expression is grouped, not the order in which C works out each operand. In a() + b() (two function calls), C may call either function first. Only a few operators, such as &&, || and the comma, guarantee left-to-right evaluation.
Common mistakes and classic precedence traps
1. Forgetting parentheses in an average
#include <stdio.h>
int main(void) {
int score1 = 80;
int score2 = 90;
printf("Wrong average: %d\n", score1 + score2 / 2);
printf("Right average: %d\n", (score1 + score2) / 2);
return 0;
}
Wrong average: 125
Right average: 85
Without parentheses, only score2 is divided by 2: 80 + 45 = 125.
2. a & b == c
if (flags & MASK == MASK) /* wrong */
if ((flags & MASK) == MASK) /* right */
This is the most famous precedence trap in C. Equality (==, level 7) is higher than bitwise AND (&, level 8), so the first line means flags & (MASK == MASK), which is flags & 1. It tests the wrong bit. GCC warns: suggest parentheses around comparison in operand of '&'. Always wrap bit tests in parentheses, as you saw in bitwise operators.
3. Shifts are lower than + and -
1 << 2 + 1 is 1 << (2 + 1), which is 8, not (1 << 2) + 1, which is 5. GCC suggests parentheses here too.
4. *p++ (a preview from pointers)
*p++ /* means *(p++): move the pointer, not the value */
(*p)++ /* adds 1 to the value p points to */
Postfix ++ (level 1) binds tighter than the dereference * (level 2). So *p++ reads the value p points to and then moves p to the next item; it does not increase the value. Don't worry if pointers are new to you; this will make full sense after C pointers and pointer arithmetic.
5. Mixing && and || without parentheses
a || b && c means a || (b && c), because && is higher. If you meant (a || b) && c, you must write the parentheses. See logical operators.
Practice exercise
🏋️ Try it yourself
Work out the values of r and s by hand, step by step, then check your answers with the program.
int r = 10 + 2 * 3 - 12 / 4 % 2;
int s = (10 + 2) * (3 - 1);
Show solution
#include <stdio.h>
int main(void) {
int r = 10 + 2 * 3 - 12 / 4 % 2;
int s = (10 + 2) * (3 - 1);
printf("r = %d\n", r);
printf("s = %d\n", s);
return 0;
}
r = 15
s = 24
For r: 2 * 3 is 6. Then 12 / 4 % 2 goes left to right: 12 / 4 is 3, and 3 % 2 is 1. Finally 10 + 6 is 16, and 16 - 1 is 15. For s, the parentheses go first: 12 * 2 = 24.
What's next?
You've finished the Operators chapter! Now put comparisons and logical operators to work by making your programs choose between paths in C if...else statements.
Key takeaways
- Operator precedence decides which operators are grouped first; * / % come before + -.
- Associativity breaks ties between operators on the same level: most go left to right, but unary, ternary and assignment operators go right to left.
- Rough order: unary, arithmetic, shifts, comparisons, bitwise, logical, ternary, assignment, comma.
- Parentheses override everything; use them for clarity whenever an expression mixes operator groups.
- == binds tighter than &, so write (flags & MASK) == MASK, not flags & MASK == MASK.
- *p++ moves the pointer, while (*p)++ changes the value it points to.
- Precedence controls grouping, not the order in which operands are evaluated.
Frequently asked questions
What is operator precedence in C?
It is the set of rules that decides which operator is applied first in an expression with several operators. For example, * has higher precedence than +, so 2 + 3 * 4 is 14.
What is associativity in C?
Associativity decides the grouping direction when operators have the same precedence. Most binary operators are left to right, so 10 - 4 - 3 is 3. Assignment is right to left, so a = b = 5 sets b first.
Which operator has the highest precedence in C?
Postfix operators such as function call (), array index [], member access . and ->, and postfix ++ and -- have the highest precedence. Parentheses used for grouping always come first.
Which operator has the lowest precedence in C?
The comma operator has the lowest precedence, followed by the assignment operators such as = and +=.
Why does a & b == c not work as expected in C?
The equality operator == has higher precedence than bitwise &, so it is read as a & (b == c). Write (a & b) == c to get the intended meaning.
Should I use parentheses even when they are not needed?
Yes, when they make the code easier to read. Parentheses have no run-time cost and prevent mistakes, especially when mixing &&, ||, bitwise operators and comparisons.