Skip to Content
Course content

14: Operator Precedence and Associativity

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I was reviewing some old code for a physics simulation recently and ran into a line that looked perfectly fine at a glance, but the output was wildly off. It's one of those moments where you stare at a single line of C for ten minutes, convinced the compiler is lying to you, only to realize you've forgotten how the language actually "reads" an expression.

Wait, that's not the math I expected

Let's recreate the scenario. Imagine we're calculating a player's total attack power. We have a base value, a multiplier for a buff, and a flat bonus. I wrote this:

int base_power = 10;
int multiplier = 2;
int bonus = 5;

int total = base_power + bonus * multiplier; 
// I was thinking: (10 + 5) * 2 = 30

When I ran this, total wasn't 30. It was 20. I remember thinking, "Wait, 10 plus 5 is 15, times 2 is 30. Why is this 20?" Then it hit me: C doesn't read left-to-right like a sentence. It follows operator precedence.

In C, multiplication (*) has a higher precedence than addition (+). The compiler sees the * and decides that bonus * multiplier must happen first. So it does 5 * 2 = 10, and then adds the base_power of 10. Result: 20. It's basic algebra, but when you're deep in a 500-line file, it's easy to forget the compiler is playing by those rules.

The fix is obvious: parentheses. They have the highest precedence of all. If I wrap the addition, I force the compiler's hand:

int total = (base_power + bonus) * multiplier; // Now it's 30

Tying the knot with Associativity

Now, precedence is easy because multiplication always beats addition. But what happens when you have two operators with the same precedence? That's where things get interesting. Let's try a different experiment.

int result = 100 / 10 * 2;

Both division (/) and multiplication (*) sit on the same level of precedence. If the compiler just picked one at random, our programs would be non-deterministic nightmares. To solve this, C uses associativity. For most operators, the associativity is left-to-right.

In my example, the compiler starts at the left:

  • First, it does 100 / 10, which is 10.
  • Then, it takes that 10 and multiplies it by 2.
  • Final result: 20.

If it had worked right-to-left, it would have done 10 * 2 = 20, then 100 / 20 = 5. Huge difference. Most of the operators you'll use daily—addition, subtraction, multiplication, division—work left-to-right. But there's a catch.

The right-to-left curveball

Not everything moves left-to-right. The most common exception is the assignment operator (=). I'll show you why this matters with a "chained assignment."

int a, b, c;
a = b = c = 50;

If this were left-to-right, C would try to do a = b first. But at that moment, b hasn't been assigned a value yet! It would be assigning garbage memory to a. Instead, the assignment operator has right-to-left associativity.

The compiler actually processes it like this: a = (b = (c = 50));. It assigns 50 to c, then the result of that operation (which is 50) gets assigned to b, and finally, that gets passed to a. It's a elegant way to initialize multiple variables to the same value in one line.

My advice? If you ever find yourself squinting at a line of code wondering if the && happens before the ||, or if a ++ is going to trigger before a +—just use parentheses. Even if you know the precedence rules by heart, parentheses make your intent clear to the next person reading your code (which might be you in six months).




📋 Practical Task

Fixing the RPG Critical Hit Formula

You are working on a combat system for an RPG. The formula for calculating "Critical Damage" is supposed to be: (Base Damage plus the Critical Bonus), all multiplied by the Critical Multiplier, and then finally reduced by the Enemy's Armor.

The current code is buggy and producing the wrong numbers because it lacks proper precedence and associativity handling. Your task is to rewrite the final_damage calculation using parentheses to ensure the operations happen in the correct order.

#include <stdio.h>

int main() {
    int base_damage = 50;
    int crit_bonus = 20;
    int crit_multiplier = 2;
    int enemy_armor = 15;

    // BUGGY LINE: This currently calculates base_damage + (crit_bonus * crit_multiplier) - enemy_armor
    int final_damage = base_damage + crit_bonus * crit_multiplier - enemy_armor;

    printf("Final Damage: %d\n", final_damage);
    // Expected Output: Final Damage: 125
    // (50 + 20) * 2 - 15 = 125
    
    return 0;
}

Requirement: Modify the final_damage line so that the output is exactly 125.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.