C Programming, General · October 14, 2026

Operator Precedence and Associativity in C

C Programming Series · Operators and Expressions


🎯 Why This Matters

Look at this line of C: 2 + 3 * 4. What is the answer? If you read left to right like a sentence, you get 5 * 4 = 20. But C says 14. Why? Because C has two sets of rules that decide in what order the parts of an expression are worked out:

  • Precedence — which operator gets done first (who has higher priority).
  • Associativity — when two operators have the same priority, which one goes first (left one or right one).

You already know a version of this from school maths: multiplication before addition. C follows very similar rules. In this post we will go through them with tiny examples, so you can predict the answer of any expression before you run it.

💡 A simple way to remember: Think of a queue at a ticket counter. Precedence is the priority pass — people with a higher pass go first. Associativity is what happens when two people have the same pass — the usual rule is that the one standing on the left goes first.

1️⃣ Precedence: Who Goes First?

Example 1: Multiplication Before Addition

#include <stdio.h>int main() {
int result = 2 + 3 * 4;
printf("2 + 3 * 4 = %d\n", result);
return 0;
}

🖥️ Output:
2 + 3 * 4 = 14

The operator * has higher precedence than +, so 3 * 4 is worked out first (giving 12), and only then 2 + 12 is done. It does not matter that + is written first.

Example 2: Parentheses Change the Order

#include <stdio.h>int main() {
int result = (2 + 3) * 4;
printf("(2 + 3) * 4 = %d\n", result);
return 0;
}

🖥️ Output:
(2 + 3) * 4 = 20

Parentheses ( ) have the highest priority of all. Whatever is inside them is worked out first, exactly like in school maths. This is your most useful tool: if you want a different order, just add parentheses.

Example 3: A Few More Quick Ones

#include <stdio.h>int main() {
printf("10 - 2 * 3 = %d\n", 10 - 2 * 3);
printf("20 / 5 + 3 = %d\n", 20 / 5 + 3);
printf("2 + 6 / 3 = %d\n", 2 + 6 / 3);
return 0;
}

🖥️ Output:
10 – 2 * 3 = 4
20 / 5 + 3 = 7
2 + 6 / 3 = 4

In each line, the * or / is done first, then the + or -. For example, 10 - 2 * 3 becomes 10 - 6, which is 4.

🪜 The Precedence Ladder

C has many operators, but you do not need to memorize all of them. Here is the ladder for the operators you have met in this course. Higher rows are done first.

The easy way to remember the top-to-bottom order:

  1. Parentheses first.
  2. Unary operators (like -x and !x).
  3. Multiply, divide, remainder (* / %).
  4. Add and subtract (+ -).
  5. Comparisons (< > <= >= == !=).
  6. Logical AND (&&), then logical OR (||).
  7. Assignment (=, += and friends) is always last.

(The bitwise and shift operators from the earlier post also have their own spots in the full ladder, between the comparison rows. We skip them here to keep things simple.)

Example 4: Unary Minus Beats Addition

#include <stdio.h>int main() {
int x = 5;
printf("-x + 2 = %d\n", -x + 2);
printf("-(x + 2) = %d\n", -(x + 2));
return 0;
}

🖥️ Output:
-x + 2 = -3
-(x + 2) = -7

In the first line, the unary minus is applied to x first (making -5), and then 2 is added. In the second line, the parentheses force x + 2 to happen first (7), and then the minus is applied.

Example 5: Arithmetic Happens Before Comparison

#include <stdio.h>int main() {
printf("5 + 3 > 2 * 3 gives %d\n", 5 + 3 > 2 * 3);
printf("5 + 3 > 2 * 4 gives %d\n", 5 + 3 > 2 * 4);
return 0;
}

🖥️ Output:
5 + 3 > 2 * 3 gives 1
5 + 3 > 2 * 4 gives 0

Both sides of the > are calculated first. The first line becomes 8 > 6, which is true (1). The second becomes 8 > 8, which is false (0). You do not need parentheses around 5 + 3 — arithmetic already outranks comparison.

Example 6: AND Goes Before OR

#include <stdio.h>int main() {
int a = 1, b = 0, c = 0; printf("a || b && c gives %d\n", a || b && c); printf("(a || b) && c gives %d\n", (a || b) && c); return 0;
}

🖥️ Output:
a || b && c gives 1
(a || b) && c gives 0

&& has higher precedence than ||. So a || b && c is really a || (b && c), which is 1 || 0, giving 1. When we add parentheses to force a || b first, we get 1 && 0, which is 0. Same symbols, different answer — all because of precedence.

Example 7: NOT Goes Before Everything Logical

#include <stdio.h>int main() {
int a = 0, b = 1; printf("!a || b gives %d\n", !a || b); printf("!(a || b) gives %d\n", !(a || b)); return 0;
}

🖥️ Output:
!a || b gives 1
!(a || b) gives 0

The ! operator is unary, so it sits near the top of the ladder. In !a || b, the ! only grabs a (making it 1), so the answer is 1 || 1 = 1. In !(a || b), the parentheses make ! apply to the whole (0 || 1), so we get !1 = 0.

Example 8: Assignment Is Always Last

#include <stdio.h>int main() {
int x = 5;
x += 2 * 3;
printf("x = %d\n", x);
return 0;
}

🖥️ Output:
x = 11

The right side 2 * 3 is worked out completely first (6). Only after that does += add it to x, giving 5 + 6 = 11. It is not (5 + 2) * 3. Assignment operators sit at the very bottom of the ladder, so everything on their right is finished before they act.

2️⃣ Associativity: The Tie-Breaker

Precedence tells us what to do when operators are different. But what about 10 - 4 - 2? Both operators are -, so they have the same precedence. Which one goes first? That is exactly what associativity decides.

Example 9: Left to Right (Most Operators)

#include <stdio.h>int main() {
printf("10 - 4 - 2 = %d\n", 10 - 4 - 2);
printf("100 / 10 / 2 = %d\n", 100 / 10 / 2);
return 0;
}

🖥️ Output:
10 – 4 – 2 = 4
100 / 10 / 2 = 5

Most operators in C, including + - * / % and the comparison and logical ones, are left to right. So 10 - 4 - 2 is worked as (10 - 4) - 2 = 4, not 10 - (4 - 2) = 8. Likewise 100 / 10 / 2 is (100 / 10) / 2 = 5.

Example 10: Multiply and Divide Are a Tie

#include <stdio.h>int main() {
printf("8 / 2 * 2 = %d\n", 8 / 2 * 2);
printf("7 / 2 * 2 = %d\n", 7 / 2 * 2);
return 0;
}

🖥️ Output:
8 / 2 * 2 = 8
7 / 2 * 2 = 6

A common mistake is to think multiplication always goes before division. They actually have the same precedence, so left to right applies. 8 / 2 * 2 is (8 / 2) * 2 = 4 * 2 = 8. The second line shows something extra: 7 / 2 is integer division (3, no decimals), so 3 * 2 = 6, not 7.

Example 11: Right to Left (Assignment)

#include <stdio.h>int main() {
int a, b, c;
a = b = c = 7; printf("a=%d b=%d c=%d\n", a, b, c); return 0;
}

🖥️ Output:
a=7 b=7 c=7

Assignment is one of the few operators that works right to left. C first does c = 7. That whole assignment gives back the value 7, which is then used for b = ..., and so on. If assignment worked left to right, this would not make sense at all.

Example 12: Precedence and Associativity Together

#include <stdio.h>int main() {
int x, y;
x = y = 3 + 4; printf("x=%d y=%d\n", x, y); return 0;
}

🖥️ Output:
x=7 y=7

Two rules work together here. Precedence: + is above =, so 3 + 4 becomes 7 first. Associativity: the two = signs are a tie, and they go right to left — y = 7 first, then x = y.

🧮 Putting It All Together: A Full Trace

Let us evaluate a longer expression using both rules, one small step at a time.

#include <stdio.h>int main() {
int result = 10 + 20 / 5 * 2 - 1;
printf("result = %d\n", result);
return 0;
}

🖥️ Output:
result = 17

Notice what happened: first / and * were handled (higher precedence than + and -), and between those two, the left one went first (associativity). Then + and - were handled, again left to right. This single recipe — highest precedence first, ties broken by associativity — solves every expression.

🛠️ Real-Life Mistakes Caused by Precedence

Example 13: Finding the Average

#include <stdio.h>int main() {
int a = 30, b = 60, c = 90; int wrong = a + b + c / 3; int right = (a + b + c) / 3; printf("wrong average = %d\n", wrong); printf("right average = %d\n", right); return 0;
}

🖥️ Output:
wrong average = 120
right average = 60

Because / goes before +, the wrong version divides only c by 3 (getting 30) and then adds 30 + 60 + 30 = 120. To average all three numbers, the addition must happen first — that is what the parentheses do.

Example 14: Celsius to Fahrenheit

#include <stdio.h>int main() {
int celsius = 100;
int fahrenheit = celsius * 9 / 5 + 32; printf("%d C = %d F\n", celsius, fahrenheit); return 0;
}

🖥️ Output:
100 C = 212 F

This one works perfectly without any parentheses. celsius * 9 is 900, then 900 / 5 is 180 (same precedence, left to right), and only then + 32 gives 212. Knowing the rules means you can tell when parentheses are needed and when they are optional.

⭐ The Golden Rule: When in Doubt, Use Parentheses

Even experienced programmers do not memorize the whole ladder. If an expression is long or you are not sure, add parentheses. They cost nothing, they never change the meaning of a correct expression, and they make your code easier for the next person (including future you) to read.

// Both are the same, but the second is easier to read
int total = price * qty + tax * 2;
int total = (price * qty) + (tax * 2);

🚫 Common Mistakes Beginners Make

MistakeWhat really happens
Reading 2 + 3 * 4 left to right as 20* has higher precedence, so the answer is 14
Writing a + b + c / 3 to find an averageOnly c is divided by 3 — you need (a + b + c) / 3
Thinking multiplication always goes before divisionThey are a tie — 8 / 2 * 2 is worked left to right
Mixing && and || without parentheses&& binds tighter than ||, which may not be what you meant
Mixing up precedence and associativityPrecedence is about different operators; associativity is the tie-breaker for the same level
Writing 1 < 5 < 3 to mean “5 is between 1 and 3”See the example below

Example 15: The “Chained Comparison” Trap

#include <stdio.h>int main() {
printf("1 < 5 < 3 gives %d\n", 1 < 5 < 3);
return 0;
}

🖥️ Output:
1 < 5 < 3 gives 1

In maths, 1 < 5 < 3 would be false. In C, comparison operators go left to right: (1 < 5) is 1, and then 1 < 3 is also true — so the answer is 1. If you want to check a range, write two comparisons joined by &&, such as x > 1 && x < 3.

🎓 Practice Exercises

Work these out on paper first, then check the answers.

Exercise 1

printf("%d", 5 + 2 * 3);

(Answer: 11 — multiply first: 5 + 6.)

Exercise 2

printf("%d", (5 + 2) * 3);

(Answer: 21 — parentheses first: 7 * 3.)

Exercise 3

printf("%d", 20 - 6 / 2 + 1);

(Answer: 18 — 6 / 2 = 3 first, then 20 - 3 + 1 left to right.)

Exercise 4

printf("%d", 2 * 3 % 4);

(Answer: 2 — * and % are a tie, so left to right: (2 * 3) % 4 = 6 % 4 = 2.)

Exercise 5

int x = 10;
x -= 2 + 3;
printf("%d", x);

(Answer: 5 — the right side 2 + 3 = 5 is finished first, then x = 10 - 5.)

Exercise 6

printf("%d", 1 < 2 && 3 > 4 || 5 > 1);

(Answer: 1 — comparisons first: 1 && 0 || 1. Then && before ||: 0 || 1 = 1.)

❓ Frequently Asked Questions

Q: Do I need to memorize the whole precedence table?
No. Remember the main order — parentheses, unary, * / %, + -, comparisons, &&, ||, assignment last — and use parentheses for anything you are unsure about.

Q: What is the difference between precedence and associativity?
Precedence decides which kind of operator goes first (like * before +). Associativity only matters when the operators are at the same level (like two - signs), and it decides whether the left one or the right one goes first.

Q: Are extra parentheses a problem?
Not at all. They do not slow your program down and they often make it clearer. Use them freely.

Q: Does precedence decide which part of an expression is calculated first in time?
Not completely. Precedence and associativity decide how the expression is grouped, but C does not always promise the order in which separate parts are evaluated. That is why modifying the same variable twice in one expression, like a++ + ++a from the Operators post, is unsafe.

✅ Key Takeaways

  • Precedence decides which operator is done first — parentheses and unary operators on top, then * / %, then + -, then comparisons, then &&, then ||, with assignment at the bottom.
  • Associativity is the tie-breaker when operators share a level — most are left to right; assignment, unary operators and ?: are right to left.
  • To solve any expression: do the highest precedence first, and break ties using associativity.
  • Parentheses always win — use them to change the order, or just to make your intent obvious.
  • Precedence mistakes compile without any error, so always double-check formulas like averages with a quick manual trace.

🚀 Next up: We will look at break and continue — two small keywords that let you leave a loop early or skip straight to its next pass, giving you finer control over how your loops behave.