Operators in C Explained — Types, Examples and Common Mistakes
- Integer division in C silently truncates — 7 / 2 is 3, not 3.5. Cast to float explicitly when you need decimals.
- = assigns, == compares. Mixing them up compiles without error but produces wrong behaviour — this is one of C's most dangerous silent bugs.
- Postfix counter++ returns the old value then increments; prefix ++counter increments first then returns the new value. The difference only matters when the result is used in an expression.
Think of operators like the buttons on a calculator. The numbers are your data, and the buttons (+, -, ×, ÷) tell the calculator WHAT TO DO with those numbers. In C, operators are the symbols that tell your program how to work with values — add them, compare them, combine them, or flip them. Without operators, your program would just be a list of numbers sitting there doing nothing.
Every useful program on the planet — from a banking app calculating your balance to a game engine deciding if a bullet hit a target — makes decisions and performs calculations. None of that is possible without operators. They are the verbs of your code. If variables are the nouns (the things), operators are the actions performed on those things. Understanding them deeply isn't optional — it's the foundation everything else is built on.
Before operators existed in programming languages, writing even simple math required multiple low-level machine instructions. C gave programmers a concise, expressive set of symbols that map closely to what the hardware actually does — which is why C is still used in embedded systems, operating systems, and performance-critical software today. Operators solve the problem of expressing computation, comparison, and logic in a way that's both human-readable and highly efficient.
By the end of this article you'll know every major category of C operator, understand exactly what each one does and why it exists, be able to read real C code without getting tripped up by symbols like >>= or !=, and you'll know the two most common operator mistakes beginners make — so you can avoid them from day one.
Arithmetic Operators — Your Program's Built-In Calculator
Arithmetic operators do exactly what the name suggests: math. C gives you six of them — addition (+), subtraction (-), multiplication (*), division (/), modulus (%), and unary negation (-). You already know the first four from school. The one that surprises beginners is modulus.
Modulus (%) gives you the REMAINDER after division. So 10 % 3 gives you 1, because 10 divided by 3 is 3 with 1 left over. This is incredibly useful in real code — use it to check if a number is even or odd, to wrap a value around a range (like keeping a game character on screen), or to cycle through array indices.
One critical thing to understand: when you divide two integers in C, you get integer division. That means 7 / 2 gives you 3, not 3.5. The decimal part is thrown away — not rounded, just discarded. This catches virtually every beginner at least once. If you need the decimal result, at least one of the operands must be a float or double.
#include <stdio.h> // Package Branding: io.thecodeforge int main() { int apples = 17; int children = 5; // Basic arithmetic int total_after_buying_more = apples + 8; // addition int eaten = apples - 3; // subtraction int doubled = apples * 2; // multiplication // Integer division: the decimal part is SILENTLY dropped int each_child_gets = apples / children; // 17 / 5 = 3 (not 3.4) // Modulus: gives the leftover after division int leftover_apples = apples % children; // 17 % 5 = 2 printf("Apples after buying more: %d\n", total_after_buying_more); printf("Apples after eating 3: %d\n", eaten); printf("Apples if we doubled: %d\n", doubled); printf("Each child gets: %d apples\n", each_child_gets); printf("Leftover apples: %d\n", leftover_apples); // To get the decimal result, use float casting float precise_share = (float)apples / children; printf("Precise share per child: %.2f apples\n", precise_share); // Checking even/odd with modulus int mystery_number = 42; if (mystery_number % 2 == 0) { printf("%d is even\n", mystery_number); } else { printf("%d is odd\n", mystery_number); } return 0; }
Apples after eating 3: 14
Apples if we doubled: 34
Each child gets: 3 apples
Leftover apples: 2
Precise share per child: 3.40 apples
42 is even
Relational and Logical Operators — Teaching Your Program to Make Decisions
Arithmetic operators crunch numbers. Relational operators compare them and return either 1 (true) or 0 (false). They're the basis of every if-statement, every loop condition, every decision your program makes. C has six: == (equal to), != (not equal to), > (greater than), < (less than), >= (greater than or equal to), and <= (less than or equal to).
Logical operators let you combine those comparisons. Think of them as the words 'and', 'or', and 'not' in English. In C: && means AND (both conditions must be true), || means OR (at least one must be true), and ! means NOT (flips true to false or false to true).
Here's a real-world framing: you're building a ride at an amusement park. The rule is: you must be AT LEAST 120cm tall AND you must be UNDER 200cm tall. That's two conditions joined by AND — exactly what && handles. If either condition is false, you don't get on the ride. This kind of gating logic appears in virtually every program ever written.
#include <stdio.h> // Standard interview logic for flow control int main() { int height_cm = 145; int age = 12; int has_parent_with_them = 1; // --- Relational Operators --- printf("height_cm > 120: %d\n", height_cm > 120); printf("height_cm > 200: %d\n", height_cm > 200); // --- Logical AND (&&) with short-circuiting --- int allowed_on_ride = (height_cm >= 120) && (height_cm <= 200); printf("\nAllowed on ride (height check): %d\n", allowed_on_ride); // --- Logical OR (||) --- int can_enter_park = (age >= 18) || (has_parent_with_them == 1); printf("Can enter park (age OR has parent): %d\n", can_enter_park); // --- Combined condition --- if (allowed_on_ride && can_enter_park) { printf("\nWelcome! Enjoy the ride!\n"); } else { printf("\nSorry, you cannot go on this ride.\n"); } return 0; }
height_cm > 200: 0
Allowed on ride (height check): 1
Can enter park (age OR has parent): 1
Welcome! Enjoy the ride!
Assignment and Compound Assignment Operators — Writing Less, Doing More
The single equals sign (=) in C is the assignment operator. It takes the value on the right and stores it in the variable on the left. It does NOT check equality — that's ==. Read it as 'gets the value of', not 'equals'.
C also gives you compound assignment operators, which combine an arithmetic operation WITH assignment into one step. Instead of writing score = score + 10, you write score += 10. They're shorthand — nothing more, nothing less. But they appear everywhere in real C code, so you need to be completely comfortable reading them.
The full set is: += (add and assign), -= (subtract and assign), *= (multiply and assign), /= (divide and assign), and %= (modulo and assign). There's also a special pair called the increment (++) and decrement (--) operators. These add or subtract exactly 1. You'll see them constantly in loops. They come in two flavours — prefix (++counter) and postfix (counter++) — and the difference matters in certain situations, so pay attention to the code below.
#include <stdio.h> int main() { int player_score = 100; // Compound assignment: += -= *= /= player_score += 50; player_score *= 2; printf("Final score after logic: %d\n", player_score); // --- Prefix vs Postfix --- int counter = 5; int a = counter++; // 'a' gets 5, then counter becomes 6 int b = ++counter; // counter becomes 7, then 'b' gets 7 printf("Postfix result: %d, Prefix result: %d, Final counter: %d\n", a, b, counter); return 0; }
Postfix result: 5, Prefix result: 7, Final counter: 7
Bitwise Operators — Working Directly With the Zeros and Ones
Every value in your computer is stored as binary — a sequence of 0s and 1s called bits. Bitwise operators let you manipulate those individual bits directly. This sounds advanced, but it's used everywhere: setting hardware flags in embedded systems, optimising memory in tight loops, building permission systems (read/write/execute flags in Linux are a perfect example), and even fast graphics programming.
C has six bitwise operators: & (AND), | (OR), ^ (XOR), ~ (NOT/complement), << (left shift), and >> (right shift). The AND and OR work bit-by-bit, just like logical && and || but on the individual bits of both operands simultaneously.
Left shift (<<) multiplies a number by powers of 2 very efficiently. Shifting left by 1 is the same as multiplying by 2, shifting left by 2 is multiplying by 4, and so on. Right shift (>>) divides by powers of 2. This is why you'll often see bitwise operations in performance-sensitive C code — they're single CPU instructions, much faster than multiplication and division.
#include <stdio.h> // Production-grade bit manipulation for flag management int main() { unsigned int READ = 1 << 2; // 0000 0100 (4) unsigned int WRITE = 1 << 1; // 0000 0010 (2) unsigned int EXECUTE = 1 << 0; // 0000 0001 (1) unsigned int user_perms = READ | WRITE; // Sets bit 2 and 1 // Checking if bit is set using AND (&) if (user_perms & READ) { printf("Access Granted: Read Enabled\n"); } // Toggling using XOR (^) user_perms ^= WRITE; printf("New Perm Value: %u\n", user_perms); return 0; }
New Perm Value: 4
| Operator Category | Purpose | Returns | Common Use Case |
|---|---|---|---|
| Arithmetic (+, -, *, /, %) | Perform math calculations | Numeric result | Score calculation, geometry, counters |
| Relational (==, !=, >, <, >=, <=) | Compare two values | 1 (true) or 0 (false) | if-conditions, loop bounds, sorting |
| Logical (&&, ||, !) | Combine boolean conditions | 1 (true) or 0 (false) | Multi-condition checks, access control |
| Assignment (=, +=, -=, *=, /=) | Store values in variables | The assigned value | Updating variables, running totals |
| Increment/Decrement (++, --) | Add or subtract 1 | Old or new value (prefix vs postfix) | Loop counters, pointer traversal |
| Bitwise (&, |, ^, ~, <<, >>) | Manipulate individual bits | Numeric result (bit pattern) | Flags, permissions, fast math, hardware |
🎯 Key Takeaways
- Integer division in C silently truncates — 7 / 2 is 3, not 3.5. Cast to float explicitly when you need decimals.
- = assigns, == compares. Mixing them up compiles without error but produces wrong behaviour — this is one of C's most dangerous silent bugs.
- Postfix counter++ returns the old value then increments; prefix ++counter increments first then returns the new value. The difference only matters when the result is used in an expression.
- Bitwise operators work on individual bits and are used for flags, permissions, and fast power-of-2 math — understanding them is what separates systems programmers from script writers.
⚠ Common Mistakes to Avoid
Interview Questions on This Topic
- QDifference between prefix and postfix increment with dry run of: int x=10; int y=x++ + ++x; What is y?
- QExplain short-circuit evaluation in logical operators (&& and ||). How does C handle the second operand if the first already determines the result?
- QHow do you check if a number is a power of 2 using bitwise operators in a single line of code? (LeetCode standard: x & (x-1) == 0)
- QWhat is the difference between bitwise AND (&) and logical AND (&&)? Provide a scenario where one is preferred over the other.
- QImplement a swap function for two integers without using a temporary variable using XOR (^).
Frequently Asked Questions
Which operator has the highest precedence in C?
Postfix operators like () (function call), [] (array subscripting), and . or -> (member access) have the highest precedence. They are evaluated before arithmetic or logical operators. Always use parentheses if you are unsure of the order of evaluation.
What is the result of a bitwise shift beyond the size of the variable?
Shifting a bit by a value equal to or greater than the number of bits in the operand is 'Undefined Behavior' in C. For example, shifting a 32-bit integer by 32 or more positions will yield unpredictable results depending on the CPU architecture.
What is the modulus operator in C and when should I use it?
The modulus operator (%) gives you the remainder after integer division. For example, 17 % 5 equals 2 because 5 goes into 17 three times with 2 left over. Use it to check if a number is even or odd (number % 2 == 0 means even), to wrap values around a range, or to cycle through a fixed set of options repeatedly.
Why do bitwise operators exist if we already have logical operators like && and ||?
Logical operators (&&, ||) work on entire values treated as true or false — they only care whether something is zero or non-zero, and they short-circuit (stop evaluating early). Bitwise operators (&, |) work on every individual bit simultaneously and never short-circuit. Bitwise operators are essential for packing multiple flags into a single integer, manipulating hardware registers, and writing memory-efficient code — tasks where logical operators simply don't have the precision needed.
Is there a 'Power' operator (like ^ in Python) in C?
No. In C, the ^ symbol is the Bitwise XOR operator. To perform exponentiation, you must use the pow(base, exponent) function from the <math.h> library or write a loop for integer powers.
Developer and founder of TheCodeForge. I built this site because I was tired of tutorials that explain what to type without explaining why it works. Every article here is written to make concepts actually click.