When an expression contains multiple operators, like a + b * c
, the compiler needs a set of rules to know which operation to perform first. These rules are known as operator precedence and associativity.
Operator Precedence
Operator precedence determines the priority of different operators. Operators with higher precedence are evaluated before operators with lower precedence.
It's very similar
to the BODMAS/PEMDAS rule in mathematics, where multiplication is done
before addition. In C, *
, /
, and %
have a higher precedence than +
and -
.
Example:
C
int result =
10 +
5 *
2;
Because
multiplication (*
) has higher precedence than addition (+
), 5 * 2
is evaluated first.
1. 5 * 2
evaluates to 10
.
2. 10 + 10
evaluates to 20
. The final value of result
is 20.
Associativity
Associativity is used when an expression has two or more operators with the same precedence level. It defines the direction in which the operations are performed: either left-to-right or right-to-left.
·
Left-to-Right
Associativity: Operations are
performed starting from the left. Most arithmetic operators (*
, /
, %
, +
, -
) have left-to-right associativity. Example: 100 / 10 * 2
Since /
and *
have the same precedence, the left-to-right rule
applies.
1. 100 / 10
is evaluated first, resulting in 10
.
2. 10 * 2
is evaluated next, resulting in 20
.
·
Right-to-Left
Associativity: Operations are
performed starting from the right. The assignment operators (=
, +=
, -=
, etc.) are a common example. Example: x = y = 5
The right-to-left rule applies.
1. y = 5
is evaluated first. The value 5
is assigned to y
.
2. The result of that assignment (5
) is then assigned to x
.
Precedence and Associativity Table (Common Operators)
Here is a simplified table showing the precedence of common C operators, from highest to lowest.
Precedence |
Operator |
Description |
Associativity |
Highest |
|
Parentheses, Array subscript, etc. |
Left-to-Right |
2 |
|
Logical NOT, Unary operators, Dereference |
Right-to-Left |
3 |
|
Multiplicative |
Left-to-Right |
4 |
|
Additive |
Left-to-Right |
5 |
|
Relational |
Left-to-Right |
6 |
|
Equality |
Left-to-Right |
... |
... |
... |
... |
Lowest |
|
Assignment |
Right-to-Left |
Using Parentheses
()
to Control Evaluation
Parentheses have the highest precedence. You can use them to force any part of an expression to be evaluated first, overriding the default precedence rules.
Rule of thumb: When in doubt, use parentheses. It makes the code clearer and prevents bugs.
Example:
C
int result_default =
10 +
5 *
2;
// Result is 20
int result_override = (
10 +
5) *
2;
// Result is 30
In
result_override
, the expression inside the parentheses (10 + 5)
is evaluated first, resulting in 15
. Then, 15 * 2
is evaluated, resulting in 30
.
Example Program
This program demonstrates how precedence and associativity affect the final results.
C
#include <stdio.h>
int main() {
int a =
20, b =
10, c =
2;
int result;
// Example 1: Precedence of '*' over '+'
result = a + b * c;
// Evaluated as 20 + (10 * 2) = 40
printf(
"Result 1 (a + b * c): %d\n", result);
// Example 2: Using parentheses to override
result = (a + b) * c;
// Evaluated as (20 + 10) * 2 = 60
printf(
"Result 2 ((a + b) * c): %d\n", result);
// Example 3: Left-to-Right associativity of '/' and '*'
result = a / b * c;
// Evaluated as (20 / 10) * 2 = 4
printf(
"Result 3 (a / b * c): %d\n", result);
// Example 4: Right-to-Left associativity of '='
a = b =
5;
// Evaluated as a = (b = 5). Now a and b are 5.
printf(
"Result 4 (a = b = 5): a=%d, b=%d\n", a, b);
return
0;
}
Operator precedence dictates how operators are grouped with operands, but an advanced understanding requires distinguishing this from the order of evaluation, which the C standard often leaves unspecified, leading to subtle bugs and undefined behavior.