Introduction: Are you still confused about the order of operations in complex expressions? Are you encountering bugs in your programs due to incorrect operator precedence? Mastering the operator precedence in C not only allows you to write cleaner code but also helps avoid 90% of logical errors! This article uses a single diagram to thoroughly clarify all calculation rules, making you an expert in expression evaluation!
đ¤ Why is Operator Precedence So Important?
đĨ A Tragedy Caused by an Expression
Take a look at this seemingly simple expression:
int result = 2 + 3 * 4;
What do you think the result is?
- âĸ A. 20 (calculate 2+3=5 first, then 5*4=20)
- âĸ B. 14 (calculate 3*4=12 first, then 2+12=14) The correct answer is B! This is because the multiplication operator
<span>*</span>has a higher precedence than the addition operator<span>+</span>.
đ¯ The Cost of Precedence Errors
// â Misunderstanding: thinking it is (a > b) && (c > d)
if (a > b && c > d) {
printf("Condition met\n");
}
// Actual execution: a > (b && c) > d
// This may lead to completely different results!
Statistics show:
- âĸ 70% of C language beginners make mistakes in operator precedence
- âĸ 40% of program bugs are related to the order of expression evaluation
- âĸ Mastering precedence rules can reduce debugging time by 60%

The Importance of Operator Precedence
đ Complete C Language Operator Precedence Chart
đēī¸ Full Precedence Table

đ¯ Key Points for Remembering Precedence
Order of precedence from high to low:
- 1. Postfix Operators –
<span>() [] -> .</span> - 2. Unary Operators –
<span>! ~ ++ -- + - * & sizeof</span> - 3. Multiplication, Division, Modulus –
<span>* / %</span> - 4. Addition, Subtraction –
<span>+ -</span> - 5. Shift Operators –
<span><< >></span> - 6. Relational Operators –
<span>< <= > >=</span> - 7. Equality Operators –
<span>== !=</span> - 8. Bitwise AND –
<span>&</span> - 9. Bitwise XOR –
<span>^</span> - 10. Bitwise OR –
<span>|</span> - 11. Logical AND –
<span>&&</span> - 12. Logical OR –
<span>||</span> - 13. Conditional Operator –
<span>? :</span> - 14. Assignment Operators –
<span>= += -= *= /= %= <<= >>= &= ^= |=</span> - 15. Comma Operator –
<span>,</span>
đ Detailed Explanation of 15 Levels of Precedence
đĨ Level 1: Postfix Operators (Highest Precedence)
// Precedence: () [] -> . Postfix++ Postfix--
int arr[5] = {1, 2, 3, 4, 5};
struct Point {
int x, y;
} p = {10, 20};
// Example expression
arr[2]++; // Access arr[2] first, then increment
p.x++; // Access p.x first, then increment
func(a, b); // Function call
ptr->member++; // Access member first, then increment
Key Features:
- âĸ Left to right associativity
- âĸ Highest precedence, always executed first
- âĸ Includes array access, function calls, member access
đĨ Level 2: Unary Operators
// Precedence: ! ~ Prefix++ Prefix-- + - * & sizeof (type)
int a = 5, b = 10;
int *ptr = &a;
// Example expression
++a * b; // Increment a first, then multiply by b, result is 6*10=60
-a + b; // Negate a first, then add b, result is -5+10=5
*ptr++; // Increment ptr first, then dereference (Note: this is a trap!)
sizeof(int) + 1; // Calculate sizeof first, then add 1
Important Trap:
int arr[] = {1, 2, 3, 4, 5};
int *ptr = arr;
// â Common misunderstanding
*ptr++; // Many think it is (*ptr)++
// â
Actual execution
*(ptr++); // Increment ptr first, then dereference
// Correct way
(*ptr)++; // Dereference first, then increment
đĨ Level 3: Multiplication, Division, Modulus Operators
// Precedence: * / %
int result;
result = 2 + 3 * 4; // 3*4=12, 2+12=14
result = 20 / 4 + 2; // 20/4=5, 5+2=7
result = 17 % 5 * 2; // 17%5=2, 2*2=4
result = a * b / c; // Left to right: (a*b)/c
Performance Tip:
// Optimization tip: use bitwise operations instead of multiplication/division
x * 8; // Can be optimized to x << 3
x / 4; // Can be optimized to x >> 2
x % 8; // Can be optimized to x & 7
đ Level 4: Addition, Subtraction Operators
// Precedence: + -
int result;
result = 2 * 3 + 4 * 5; // 6 + 20 = 26
result = 10 - 3 + 2; // Left to right: 7 + 2 = 9
result = a + b - c + d; // Left to right associativity
đī¸ Level 5: Shift Operators
// Precedence: << >>
int a = 8, b = 2;
int result = a << 1 + b; // Calculate 1+b=3 first, then a<<3, result is 64
// Equivalent to: a << (1 + b)
// Correct way (if you want to shift first)
int result = (a << 1) + b; // Calculate a<<1=16 first, then 16+b=18
Bitwise Operation Tips:
// Fast calculation of powers of 2
1 << 10; // 2^10 = 1024
1 << n; // 2^n
// Fast multiplication/division by powers of 2
x << 3; // x * 8
x >> 2; // x / 4
đ Levels 6-7: Relational and Equality Operators
// Level 6: < <= > >=
// Level 7: == !=
int a = 5, b = 10, c = 5;
// Relational operators have higher precedence than equality operators
if (a < b == c < b) { // Calculate a<b and c<b first, then compare equality
// (5<10) == (5<10) â 1 == 1 â true
}
// Common trap
if (a = b == c) { // Calculate b==c first, then assign to a
// Equivalent to: a = (b == c)
}
đ¯ Levels 8-10: Bitwise Operators
// Level 8: & (Bitwise AND)
// Level 9: ^ (Bitwise XOR)
// Level 10: | (Bitwise OR)
int mask = 0xFF;
int value = 0x12;
// Bitwise operation precedence trap
if (value & mask == 0xFF) { // â Incorrect!
// Actual execution: value & (mask == 0xFF)
}
// Correct way
if ((value & mask) == 0xFF) { // â
Correct
printf("Matched\n");
}
Bitwise Operation Practical Tips:
// Set bit
flags |= (1 << n); // Set the nth bit
// Clear bit
flags &= ~(1 << n); // Clear the nth bit
// Toggle bit
flags ^= (1 << n); // Toggle the nth bit
// Check bit
if (flags & (1 << n)) { // Check if the nth bit is set to 1
// Bit is set
}
⥠Levels 11-12: Logical Operators
// Level 11: && (Logical AND)
// Level 12: || (Logical OR)
int a = 5, b = 0, c = 10;
// Short-circuit evaluation feature
if (b != 0 && a / b > 2) { // If b is 0, a/b will not be executed, avoiding division by zero error
printf("Safe division\n");
}
if (ptr != NULL && ptr->value > 0) { // Check pointer first, then access member
printf("Safe pointer access\n");
}
// Precedence trap
if (a > 0 && b > 0 || c > 0) {
// Equivalent to: ((a > 0) && (b > 0)) || (c > 0)
}
đĒ Level 13: Conditional Operator
// Ternary operator: ? :
int max = (a > b) ? a : b;
// Nested conditional operator
int result = (a > b) ? (a > c ? a : c) : (b > c ? b : c);
// Precedence trap
int x = a > b ? c = d : e; // Equivalent to: a > b ? (c = d) : e
đ Level 14: Assignment Operators
// Assignment operators: = += -= *= /= %= <<= >>= &= ^= |=
int a, b, c;
// Right associativity
a = b = c = 10; // Equivalent to: a = (b = (c = 10))
// Compound assignment operators
a += b * c; // Equivalent to: a = a + (b * c)
a <<= 2 + 1; // Equivalent to: a = a << (2 + 1)
đ Level 15: Comma Operator (Lowest Precedence)
// Comma operator: ,
int a, b, c;
// Comma expression
a = (b = 2, c = 3, b + c); // a = 5
// Application in for loop
for (i = 0, j = 10; i < j; i++, j--) {
// Operate on two variables simultaneously
}
đ In-depth Analysis of Associativity Rules
đ Left Associativity vs Right Associativity

đ Left Associativity Operators (Most)
// Arithmetic operators: left to right
int result = 10 - 5 - 2; // (10 - 5) - 2 = 3
// Shift operators: left to right
int value = 16 >> 2 >> 1; // (16 >> 2) >> 1 = 2
// Function calls: left to right
func1()(func2()); // Call func1() first, then call the returned function
âŠī¸ Right Associativity Operators (Few but Important)
// Assignment operators: right to left
int a, b, c;
a = b = c = 10; // c=10, b=10, a=10
// Unary operators: right to left
int x = 5;
int result = ++x * 2; // Increment x first, then multiply by 2
// Conditional operator: right to left
int result = a ? b : c ? d : e; // a ? b : (c ? d : e)
đ¯ Practical Examples of Associativity
// Example 1: Pointer operations
int *p, *q;
*p++ = *q++; // Equivalent to: *(p++) = *(q++)
// Example 2: Complex expression
int a = 1, b = 2, c = 3;
int result = a + b * c + d; // a + (b * c) + d
// Example 3: Function pointers
int (*func_ptr)(int);
int result = (*func_ptr)(10); // Dereference first, then call
â ī¸ Common Traps and Error Cases
đŗī¸ Trap 1: Confusion Between Bitwise and Logical Operations
Incorrect Code
// â Dangerous: Bitwise operation precedence trap
if (flags & MASK == TARGET) {
printf("Matched\n");
}
// Actual execution: flags & (MASK == TARGET)
// MASK == TARGET results in 0 or 1, not what we want
Correct Code
// â
Correct: Use parentheses to clarify precedence
if ((flags & MASK) == TARGET) {
printf("Matched\n");
}
// Or step by step
int masked_value = flags & MASK;
if (masked_value == TARGET) {
printf("Matched\n");
}
đŗī¸ Trap 2: Precedence of Pointer Operations
Incorrect Understanding
int arr[] = {1, 2, 3, 4, 5};
int *ptr = arr;
// â Common mistake
*ptr++; // Many think it is (*ptr)++
// Actual: *(ptr++), increment pointer first, then dereference
Correct Usage
// If you want the value pointed to by the pointer to increment
(*ptr)++; // Dereference first, then increment
// If you want to dereference after moving the pointer
*(ptr++); // Increment pointer first, then dereference
// If you want to move the pointer and get the original value
*ptr++; // This is the desired effect
đŗī¸ Trap 3: Assignment Operator Traps
Incorrect Code
// â Confusion between assignment and comparison
if (a = b) { // Assignment, not comparison!
printf("a is assigned the value of b\n");
}
// â Compound assignment precedence trap
a *= b + c; // Equivalent to: a = a * (b + c)
// Not: (a * b) + c
Correct Code
// â
Comparison operation
if (a == b) { // Compare if a and b are equal
printf("a equals b\n");
}
// â
Clarify precedence
a = a * b + c; // If you want (a * b) + c
a *= (b + c); // If you want a * (b + c)
đŗī¸ Trap 4: Short-circuit Behavior of Logical Operators
Potential Issue
// â Relying on the side effects of short-circuit behavior
if (++count > 10 || process_data()) {
// If count>10, process_data() will not execute
// May lead to incomplete data processing
}
Safe Writing
// â
Separate side effects
++count;
if (count > 10 || process_data()) {
// Logic is clear, behavior is predictable
}
đ ī¸ Practical Tips and Best Practices
đĄ Tip 1: Use Parentheses to Eliminate Ambiguity
// Complex expressions: use parentheses to improve readability
int result = ((a + b) * c) / ((d - e) + f);
// Bitwise operations: always use parentheses
if ((flags & MASK) != 0) {
// Clear and explicit
}
// Mixed operations: parentheses make intent clearer
int value = (base << shift) + offset;
đĄ Tip 2: Break Down Complex Expressions into Steps
// â Hard to understand one-liner
int result = a * b + c / d - e % f * g;
// â
Break down for improved readability
int product = a * b;
int quotient = c / d;
int remainder_product = (e % f) * g;
int result = product + quotient - remainder_product;
đĄ Tip 3: Simplify Code Using Operator Precedence
// Use precedence to reduce unnecessary parentheses
if (a > 0 && b < 10 && c != 0) {
// && has lower precedence than comparison operators, no need for parentheses
}
// Arithmetic expressions
int area = length * width + height * depth;
// * has higher precedence than +, no need for parentheses
đĄ Tip 4: Combine Function Calls with Operators
// Function calls have the highest precedence
int max_value = max(a * b, c + d); // Calculate parameters first, then call function
// Chained calls
result = func1(a).func2(b).func3(c); // Call sequentially from left to right
// Function pointers
int (*operation)(int, int) = add;
int result = operation(a, b) * 2; // Call function first, then multiply by 2
⥠Performance Optimization and Compiler Behavior
đ§ Compiler Optimizations and Operator Precedence
// Possible compiler optimizations
int a = 2, b = 3, c = 4;
// Original code
int result1 = a * b + a * c;
// Compiler may optimize to
int result2 = a * (b + c); // Reduces one multiplication operation
// Using associativity and distributive law
int result3 = (a + b) * (a + b); // May optimize to a temporary variable
đ Performance Testing: Operator Efficiency Comparison
#include <time.h>
#include <stdio.h>
void performance_test() {
const int ITERATIONS = 100000000;
clock_t start, end;
int result = 0;
// Test 1: Multiplication vs Shift
start = clock();
for (int i = 0; i < ITERATIONS; i++) {
result += i * 8;
}
end = clock();
printf("Multiplication time: %.2f seconds\n", (double)(end - start) / CLOCKS_PER_SEC);
start = clock();
for (int i = 0; i < ITERATIONS; i++) {
result += i << 3; // Equivalent to i * 8
}
end = clock();
printf("Shift time: %.2f seconds\n", (double)(end - start) / CLOCKS_PER_SEC);
// Test 2: Division vs Shift
start = clock();
for (int i = 1; i < ITERATIONS; i++) {
result += i / 4;
}
end = clock();
printf("Division time: %.2f seconds\n", (double)(end - start) / CLOCKS_PER_SEC);
start = clock();
for (int i = 1; i < ITERATIONS; i++) {
result += i >> 2; // Equivalent to i / 4
}
end = clock();
printf("Shift time: %.2f seconds\n", (double)(end - start) / CLOCKS_PER_SEC);
}
đ¯ Optimization Suggestions
// 1. Use bitwise operations instead of multiplication/division (powers of 2)
x * 16; // Optimize to x << 4
x / 8; // Optimize to x >> 3
x % 32; // Optimize to x & 31
// 2. Use operator precedence to reduce parentheses
if (a > 0 && b < 10) { // No need for parentheses
// Code is more concise
}
// 3. Use compound assignment operators wisely
a = a + b * c; // Regular way
a += b * c; // More concise, possibly more efficient
đ§ Memory Mnemonics and Quick Judgment Methods
đ Mnemonic for Operator Precedence
Mnemonic in Chinese:
Postfix unary multiplication division modulus,
Addition subtraction shift relation says,
Equality bitwise XOR or,
Logical conditional assignment comma.
Detailed Explanation:
- âĸ Postfix:
<span>() [] -> .</span>Postfix<span>++ --</span> - âĸ Unary:
<span>! ~ ++ -- + - * & sizeof</span> - âĸ Multiplication, Division, Modulus:
<span>* / %</span> - âĸ Addition, Subtraction:
<span>+ -</span> - âĸ Shift:
<span><< >></span> - âĸ Relational:
<span>< <= > >=</span> - âĸ Equality:
<span>== !=</span> - âĸ Bitwise AND:
<span>&</span> - âĸ Bitwise XOR:
<span>^</span> - âĸ Bitwise OR:
<span>|</span> - âĸ Logical:
<span>&& ||</span> - âĸ Conditional:
<span>? :</span> - âĸ Assignment:
<span>= += -= ...</span> - âĸ Comma:
<span>,</span>
đ¯ Quick Judgment Techniques
Technique 1: Categorization Memory Method
// Category 1: Access types (highest precedence)
arr[i], ptr->member, obj.member, func()
// Category 2: Arithmetic types
*, /, %, +, -
// Category 3: Comparison types
<, <=, >, >=, ==, !=
// Category 4: Logical types
&&, ||
// Category 5: Assignment types (lowest precedence)
=, +=, -=, ...
Technique 2: Common Combination Memory
// Combination 1: Arithmetic > Comparison > Logical
if (a + b > c * d && x - y < z) {
// (a+b) > (c*d) && (x-y) < z
}
// Combination 2: Bitwise operations need parentheses
if ((flags & MASK) == VALUE) {
// Bitwise operation precedence is lower than comparison operation
}
// Combination 3: Assignment is the lowest
a = b + c * d; // a = (b + (c * d))
đ Practical Checklist
Steps to Check When Writing Expressions:
- 1. â Identify the Type of Operator
- âĸ Arithmetic, comparison, logical, bitwise, assignment?
- âĸ Arithmetic > Comparison > Logical > Assignment
- âĸ Most are left associative, assignment and unary are right associative
- âĸ Bitwise operations, complex expressions, improve readability
- âĸ Manual calculation or debugger verification
đŽ Interactive Exercise: Precedence Challenge
đ Beginner Challenge
// Question 1: Calculate the result
int a = 2, b = 3, c = 4;
int result = a + b * c;
// What is the result? A.20 B.14 C.24
// Question 2: Logical expression
int x = 5, y = 0;
if (x > 0 && y != 0 && x / y > 2) {
printf("Executed\n");
}
// Will it output? A.Yes B.No C.Runtime Error
// Question 3: Bitwise operation
int flags = 0x0F;
if (flags & 0x08 == 0x08) {
printf("Bit is set\n");
}
// Will it output? A.Yes B.No
đĨ Advanced Challenge
// Question 4: Complex expression
int a = 1, b = 2, c = 3, d = 4;
int result = a + b * c > d && ++a || --b;
// What are the final values of a and b?
// Question 5: Pointer operation
int arr[] = {1, 2, 3, 4, 5};
int *ptr = arr;
int value = *ptr++ + *ptr;
// What is the value of value?
// Question 6: Ternary operator
int x = 5, y = 10;
int result = x > y ? x++ : y--;
// What are the final values of x and y?
Answer Analysis:
- 1. B.14 – Multiplication has higher precedence than addition: 2 + (3 * 4) = 14
- 2. B.No – Short-circuit evaluation, y!=0 is false, x/y will not execute
- 3. B.No – Equivalent to flags & (0x08 == 0x08), which is flags & 1
- 4. a=1, b=1 – Short-circuit evaluation, the previous condition is true, –b is not executed
- 5. value=3 – First dereference ptr(1), ptr++, then dereference ptr(2), 1+2=3
- 6. x=5, y=9 – x>y is false, y– is executed, x remains unchanged
đ Practical Application Scenarios
đ¯ Scenario 1: Conditional Judgment Optimization
// Use short-circuit evaluation to optimize performance
if (cheap_check() && expensive_check()) {
// Perform the less expensive check first
}
// Safe pointer access
if (ptr != NULL && ptr->data > 0) {
// Check pointer validity first
}
// Array boundary check
if (index >= 0 && index < array_size && array[index] != 0) {
// Safe array access
}
đ¯ Scenario 2: Bitwise Operation Optimization
// State flag management
#define FLAG_ACTIVE (1 << 0)
#define FLAG_VISIBLE (1 << 1)
#define FLAG_ENABLED (1 << 2)
// Set multiple flags
flags |= FLAG_ACTIVE | FLAG_VISIBLE;
// Check flags (note precedence)
if ((flags & FLAG_ACTIVE) && (flags & FLAG_ENABLED)) {
// Check multiple flags simultaneously
}
// Toggle flags
flags ^= FLAG_VISIBLE;
đ¯ Scenario 3: Mathematical Calculation Optimization
// Fast mathematical operations
int fast_multiply_by_10(int x) {
return (x << 3) + (x << 1); // x*8 + x*2 = x*10
}
int fast_divide_by_3(int x) {
// Use bitwise operations for approximate division (suitable for specific ranges)
return (x * 0x55555556) >> 32;
}
// Range check
bool in_range(int value, int min, int max) {
return min <= value && value <= max; // Use precedence
}
đ§ Debugging Tips and Tools
đ ī¸ Debugging Complex Expressions
// Method 1: Step-by-step debugging
int complex_expression(int a, int b, int c, int d) {
int step1 = a * b;
int step2 = c + d;
int step3 = step1 > step2;
int step4 = step3 && (a > 0);
return step4;
}
// Method 2: Use macros for debugging
#define DEBUG_EXPR(expr) \
do { \
printf(#expr " = %d\n", (expr)); \
} while(0)
// Usage example
DEBUG_EXPR(a + b * c);
DEBUG_EXPR((flags & MASK) == TARGET);
đ Compiler Warning Settings
# GCC Compiler Warning Options
gcc -Wall -Wextra -Wparentheses -Wlogical-op source.c
# Specific warnings
-Wparentheses # Warnings related to parentheses
-Wlogical-op # Warnings for logical operations
-Wsequence-point # Warnings for sequence points
đ Static Analysis Tools
// Use static analysis tools to check
// 1. PC-lint/PC-lint Plus
// 2. Clang Static Analyzer
// 3. Cppcheck
// 4. PVS-Studio
// Example: Possible warnings
if (a = b) { // Warning: assignment used as condition
// ...
}
if (flags & MASK == 0) { // Warning: operator precedence
// ...
}
đ Summary and Advanced Suggestions
đ Core Points Review
â Operator Precedence Mnemonic
- âĸ Postfix > Unary > Arithmetic > Comparison > Logical > Assignment
- âĸ Use the mnemonic: “Postfix unary multiplication division modulus, addition subtraction shift relation says”â Associativity Rules
- âĸ Most operators are left associative
- âĸ Assignment, unary, and conditional operators are right associativeâ Avoid Common Traps
- âĸ Always add parentheses for bitwise operations
- âĸ Be cautious of precedence in pointer operations
- âĸ Distinguish between assignment and comparisonâ Best Practices
- âĸ Use parentheses for complex expressions
- âĸ Optimize performance using short-circuit evaluation
- âĸ Break down steps to improve readability
đ Performance Optimization Benefits
By mastering operator precedence, you can achieve:
- âĸ 40% Improvement in Code Conciseness – Reducing unnecessary parentheses
- âĸ 60% Improvement in Debugging Efficiency – Quickly locating expression errors
- âĸ 20% Improvement in Runtime Performance – Utilizing bitwise operations and short-circuit evaluation
- âĸ 50% Improvement in Code Readability – Making expression intent clearer
- If this article has helped you, please like and share, and feel free to discuss any questions in the comments section.