Operators
Operators combine values: arithmetic, comparison, logic and assignment. C's operators are compact and powerful — several were copied by almost every language since — but a few, like increment and integer division, need care.
Arithmetic
#include <stdio.h> int main(void) { int a = 17, b = 5; printf("%d + %d = %d\n", a, b, a + b); printf("%d - %d = %d\n", a, b, a - b); printf("%d * %d = %d\n", a, b, a * b); printf("%d / %d = %d\n", a, b, a / b); printf("%d %% %d = %d\n", a, b, a % b); printf("-17 / 5 = %d, -17 %% 5 = %d\n", -17 / 5, -17 % 5); return 0; }
17 + 5 = 22 17 - 5 = 12 17 * 5 = 85 17 / 5 = 3 17 % 5 = 2 -17 / 5 = -3, -17 % 5 = -2
Integer division truncates toward zero, and % (remainder) takes the sign of the left operand. % only works on integers; use fmod for floating point. Dividing an integer by zero is undefined behaviour — always check the divisor.
Assignment operators
#include <stdio.h> int main(void) { int score = 10; score += 5; // score = score + 5 score *= 2; // score = score * 2 score -= 4; // score = score - 4 score /= 2; // score = score / 2 score %= 7; // score = score % 7 printf("%d\n", score); return 0; }
6
Increment and decrement
++ adds one and -- subtracts one. Prefix (++x) changes the variable and gives the new value; postfix (x++) gives the old value, then changes it:
#include <stdio.h> int main(void) { int x = 5; int a = x++; // a = 5, then x = 6 int b = ++x; // x = 7, then b = 7 printf("a=%d b=%d x=%d\n", a, b, x); return 0; }
a=5 b=7 x=7
Use them as stand-alone statements (count++;) and the difference doesn't matter. Never change the same variable twice in one expression, as in i = i++ or printf("%d %d", i++, i++) — that's undefined behaviour.
Comparison
Comparisons produce 1 (true) or 0 (false), as an int:
#include <stdio.h> int main(void) { int age = 20; printf("%d %d %d\n", age == 20, age != 20, age >= 18); printf("%d %d\n", age < 13, age > 65); return 0; }
1 0 1 0 0
== compares; a single = assigns. Mixing them up is a classic bug that the compiler warns about (lesson 4).
Logical operators
| Operator | True when |
|---|---|
a && b | both are true |
a || b | at least one is true |
!a | a is false |
In C, zero is false and any other value is true. && and || short-circuit: they stop as soon as the answer is known, so the right side may never run. That's how you safely guard a risky check:
#include <stdio.h> int main(void) { int count = 0, total = 50; if (count != 0 && total / count > 10) { printf("high average\n"); } else { printf("no division happened\n"); } printf("%d %d %d\n", !0, !5, 3 && 0); return 0; }
no division happened 1 0 0
The conditional operator
condition ? a : b chooses between two values:
#include <stdio.h> int main(void) { int items = 1; printf("%d item%s\n", items, items == 1 ? "" : "s"); items = 3; printf("%d item%s\n", items, items == 1 ? "" : "s"); int a = 8, b = 13; printf("max = %d\n", a > b ? a : b); return 0; }
1 item 3 items max = 13
Precedence
Operators bind with different strength, so 2 + 3 * 4 is 14. A short version of the table, highest first:
| Level | Operators |
|---|---|
| Postfix | x++ x-- () [] . -> |
| Unary | ++x --x ! ~ - + * & sizeof (type) |
| Multiplicative | * / % |
| Additive | + - |
| Shifts | << >> |
| Relational | < <= > >= |
| Equality | == != |
| Bitwise | &, then ^, then | |
| Logical | &&, then || |
| Conditional | ?: |
| Assignment | = += -= … |
| Comma | , |
When in doubt, add parentheses — they cost nothing and make intent clear. Bitwise operators are a known trap: flags & MASK == 0 means flags & (MASK == 0).
Try it yourself
Check whether a year is a leap year: divisible by 4, except century years, which must be divisible by 400.
1900: not a leap year 2000: leap year 2024: leap year 2026: not a leap year