Skip to content

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.

LevelOperatorsDescriptionAssociativity
1() [] -> . x++ x--function call, array index, member access, postfixleft to right
2++x --x + - ! ~ * & sizeof (type)prefix, unary plus/minus, NOT, dereference, address-of, castright to left
3* / %multiply, divide, remainderleft to right
4+ -add, subtractleft to right
5<< >>bit shiftsleft to right
6< <= > >=relational comparisonsleft to right
7== !=equalityleft to right
8&bitwise ANDleft to right
9^bitwise XORleft to right
10|bitwise ORleft to right
11&&logical ANDleft to right
12||logical ORleft to right
13?:conditional (ternary)right to left
14= += -= *= /= %= &= |= ^= <<= >>=assignmentright to left
15,commaleft 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.

Animation evaluating 4 + 6 * 2 - 8 / 4. Step 1: 6 * 2 becomes 12. Step 2: 8 / 4 becomes 2. Step 3: 4 + 12 becomes 16. Step 4: 16 - 2 becomes 14. The result is 14
* and / are grouped first, then + and - from left to right.
#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.