Lesson Progress
0%
Lesson  ยท  Operator Precedence & Associativity

Which Operator Runs First?

C never evaluates an expression left to right by default โ€” every operator has a rank, and higher-ranked operators fire first. This brief chapter covers the rules that actually bite beginners, with a short reference table and five quick examples.

Precedence vs associativity
Arithmetic order
Logical & relational
Bitwise vs equality
= vs ==
๐Ÿ“–

Precedence vs Associativity โ€” Two Different Rules

Precedence decides which operator gets evaluated first when two different operators sit next to each other โ€” * outranks +, so 2 + 3 * 4 is 2 + 12, not 5 * 4.

Associativity only matters when operators of the same rank appear together, and decides which direction they group โ€” left-to-right or right-to-left. 20 - 5 - 2 groups left-to-right as (20 - 5) - 2 = 13, while a = b = 5 groups right-to-left as a = (b = 5).

Category (high โ†’ low)OperatorsAssociativity
Postfix() [] -> . i++ i--Left โ†’ Right
Unary++i --i + - ! ~ sizeof (type)Right โ†’ Left
Multiplicative* / %Left โ†’ Right
Additive+ -Left โ†’ Right
Shift<< >>Left โ†’ Right
Relational< <= > >=Left โ†’ Right
Equality== !=Left โ†’ Right
Bitwise AND&Left โ†’ Right
Bitwise XOR^Left โ†’ Right
Bitwise OR|Left โ†’ Right
Logical AND&&Left โ†’ Right
Logical OR||Left โ†’ Right
Ternary?:Right โ†’ Left
Assignment= += -= *= /=Right โ†’ Left
๐Ÿ’ก When in doubt, add parentheses. Nobody memorizes this whole table while coding โ€” professional C code uses () liberally to make intent obvious, even when the default precedence would already give the right answer.
example 1
1

Arithmetic: * and / Outrank + and -

The classic BODMAS rule
Example 1 ยท arithmetic_precedence.c
arithmetic_precedence.c
C
#include <stdio.h>

int main() {
    int a = printf("2 + 3 * 4     = %d\n", 2 + 3 * 4);      // * first: 2 + 12
    printf("(2 + 3) * 4   = %d\n", (2 + 3) * 4);              // parens override
    printf("10 - 4 / 2    = %d\n", 10 - 4 / 2);                // / first: 10 - 2
    printf("20 %% 6 + 1    = %d\n", 20 % 6 + 1);                // %% first: 2 + 1
    return 0;
}
terminal
output
2 + 3 * 4     = 14
(2 + 3) * 4   = 20
10 - 4 / 2    = 8
20 % 6 + 1    = 3
example 2
2

Relational Binds Tighter Than Logical

< > == before && ||

Relational operators (< > == !=) always run before logical operators (&& ||). This means age > 18 && marks > 50 is safe to write without extra parentheses โ€” but adding them anyway is good practice for readability.

Example 2 ยท relational_logical.c
relational_logical.c
C
#include <stdio.h>

int main() {
    int age = 20, marks = 65;

    // evaluated as: (age > 18) && (marks > 50)
    if (age > 18 && marks > 50)
        printf("Eligible\n");
    else
        printf("Not eligible\n");

    // == also outranks &&, so this compares first, combines second
    int result = age == 20 && marks == 65;
    printf("result = %d\n", result);

    return 0;
}
terminal
output
Eligible
result = 1
example 3
3

The Bitwise-vs-Equality Trap

& and | rank BELOW ==

This one surprises even experienced programmers: bitwise & and | have lower precedence than ==. Writing if (flags & MASK == 0) does NOT check "is the masked bit zero" โ€” it secretly evaluates MASK == 0 first.

Example 3 ยท bitwise_trap.c
bitwise_trap.c
C
#include <stdio.h>

int main() {
    int flags = 6;      // binary 110
    int MASK  = 2;      // binary 010

    // WRONG (but compiles!): == runs before &, so this is flags & (MASK == 0)
    //                        = flags & 0  =  0   (always false, silently)
    printf("flags & MASK == 0  ->  %d  (misleading!)\n", flags & MASK == 0);

    // RIGHT: force the bitwise AND to happen first
    printf("(flags & MASK) == 0 -> %d  (correct)\n", (flags & MASK) == 0);

    return 0;
}
terminal
output
flags & MASK == 0  ->  0  (misleading!)
(flags & MASK) == 0 -> 0  (correct)
โš ๏ธ Both lines print 0 here โ€” which is exactly what makes this bug so dangerous. It compiles cleanly and often produces a coincidentally "reasonable-looking" result, hiding for a long time until different input values expose the mismatch. Always parenthesize bitwise operations mixed with comparisons.
example 4
4

= (Assignment) vs == (Equality)

One character, very different jobs

= assigns a value and, as an expression, evaluates to that same value. Since C allows assignments inside if conditions, typing = instead of == by mistake doesn't cause an error โ€” it silently assigns and then tests whatever value was assigned.

Example 4 ยท assignment_vs_equality.c
assignment_vs_equality.c
C
#include <stdio.h>

int main() {
    int flag = 0;

    // BUG: this ASSIGNS 5 to flag, then tests "is 5 truthy?" -> always true
    if (flag = 5) {
        printf("This always runs! flag is now %d\n", flag);
    }

    flag = 0;   // reset

    // CORRECT: == compares without changing flag
    if (flag == 5) {
        printf("Won't print.\n");
    } else {
        printf("Correctly false. flag is still %d\n", flag);
    }

    return 0;
}
terminal
output
This always runs! flag is now 5
Correctly false. flag is still 0
๐Ÿ’ก A defensive habit: some programmers write comparisons as if (5 == flag) โ€” if you accidentally type one =, the compiler flags "5 = flag" as an error immediately, since 5 isn't a variable you can assign to.
example 5
5

Right-to-Left Associativity: Unary & Ternary

Not everything goes left to right

Unary operators (++i, -x, sizeof) and the ternary ?: associate right-to-left โ€” the opposite of most operators. This is what lets a = b = c = 5; chain naturally: it's really a = (b = (c = 5)).

Example 5 ยท right_to_left.c
right_to_left.c
C
#include <stdio.h>

int main() {
    int a, b, c;
    a = b = c = 5;   // groups right-to-left: a = (b = (c = 5))
    printf("a=%d b=%d c=%d\n", a, b, c);

    int marks = 72;
    // ternary is right-to-left too, but here it's just one condition
    char *result = (marks >= 50) ? "Pass" : "Fail";
    printf("Result: %s\n", result);

    int x = 5;
    printf("-x * 2 = %d\n", -x * 2);   // unary - binds to x first, then *2

    return 0;
}
terminal
output
a=5 b=5 c=5
Result: Pass
-x * 2 = -10
โš ๏ธ Avoid i++ + ++i in the same expression. When the same variable is modified more than once between sequence points, the result is undefined behavior in C โ€” different compilers may give different answers. Precedence tells you grouping, not the order side effects happen in.
quiz
Q

Quick Quiz

Question 1 of 4

What does 2 + 3 * 4 evaluate to?

Question 2 of 4

Why does flags & MASK == 0 often behave unexpectedly?

Question 3 of 4

What's wrong with if (flag = 5) when the intent was a comparison?

Question 4 of 4

Which operators associate right-to-left?

โœ“

Lesson Checklist

  • I understand the difference between precedence and associativity
  • I know * and / outrank + and -
  • I know relational operators outrank && and ||
  • I know == outranks bitwise & and | โ€” and always parenthesize when mixing them
  • I can explain the = vs == bug in an if condition
  • I know assignment and unary operators associate right-to-left
  • I completed the quiz