Operators in C
October 4, 2026 • 6 min read

Table of contents
Part of the series:C Explained
An operator is a symbol that computes a new value from one or more values. C has a small set of them, and once you know them you can express almost any calculation. This post goes through them group by group. The conditionals and loops that use these comparisons have their own posts, so they are not repeated here.
Arithmetic operators
The five basic ones should look familiar from math:
int sum = 10 + 5; // 15 addition
int diff = 10 - 5; // 5 subtraction
int prod = 10 * 5; // 50 multiplication
int quot = 10 / 3; // 3 division (integers cut the fraction)
int rem = 10 % 3; // 1 remainder (modulo)
Remember from the data types post: / on two integers is integer division and % needs integers. If at least one operand is a decimal, / does floating-point division.
Assignment operators
The plain = assigns a value. C also provides compound operators that combine assignment with arithmetic. a += 5 means “add 5 to a”:
int a = 10;
a += 5; // a is 15
a -= 3; // a is 12
a *= 2; // a is 24
a /= 4; // a is 6
a %= 4; // a is 2
There are matching versions for every binary operator, including the bitwise ones below. Read a += 5 as shorthand for a = a + 5; the value is stored back into the same variable.
Increment and decrement
++ adds one, -- subtracts one. Where you put it matters:
int x = 5;
x++; // x is now 6 (post-increment: returns old value)
++x; // x is now 7 (pre-increment: returns new value)
int x = 5;
int a = x++; // a = 5, x = 6
int b = ++x; // x = 7, b = 7
x++ gives you the value before the increment; ++x gives the value after. When the result is not used (a standalone x++; line) the two are identical. C programmers use them heavily in loops.
Relational (comparison) operators
These compare two values and produce 1 (true) or 0 (false):
10 > 5 // 1 greater than
10 < 5 // 0 less than
10 >= 5 // 1 greater or equal
10 <= 5 // 0 less or equal
10 == 5 // 0 equal (two equals signs!)
10 != 5 // 1 not equal
The classic beginner bug is writing = when you mean ==. = assigns and == compares, and the compiler may not catch the mix-up in an if. If you wonder why C lets you put an assignment inside a condition, you are not alone; that is one of the language’s darker corners, covered in the conditionals post.
Logical operators
These combine true/false values:
flag1 && flag2 // AND: 1 only if both are true
flag1 || flag2 // OR: 1 if at least one is true
!flag // NOT: flips the value
int age = 25;
age >= 18 && age <= 65 // 1: adult and of working age
age < 18 || age > 65 // 0: neither child nor senior
&& and || are short-circuit: C evaluates the left side first and only evaluates the right side if needed. With &&, if the left is false the right is never evaluated; with ||, if the left is true the right is skipped. That is safe for the common guard pattern like ptr != NULL && *ptr == 5, which would crash if evaluated left-to-right without short-circuiting.
Bitwise operators
These work on the individual bits of the value. You rarely need them in application code, but they are what make C the language of low-level programming:
~a // NOT: flips every bit
a & b // AND: 1 only where both bits are 1
a | b // OR: 1 where at least one bit is 1
a ^ b // XOR: 1 where the bits differ
a << n // shift all bits left by n (like multiplying by 2^n)
a >> n // shift all bits right by n (like dividing by 2^n)
int flags = 0b00001100; // 12
flags = flags << 1; // 0b00011000 (24)
int masked = 12 & 0b00001010; // 0b00001000 (8)
Common uses: packing flags into a single byte, reading hardware registers, and fast multiply/divide by powers of two.
The conditional (ternary) operator
C has one three-part operator, a compact if/else that evaluates to a value:
int max = (a > b) ? a : b;
Read it as “if the condition is true, take the first value, otherwise the second.” It is just a shortcut; anything you write with it can be written with a full if/else, which you will meet in the next post.
The comma operator and sizeof
The comma operator evaluates several expressions in order and keeps the last value, usually inside for loops to update multiple variables:
int i, j;
for (i = 0, j = 10; i < j; i++, j--) {
// ...
}
sizeof is technically an operator, not a function: it returns the size in bytes of a type or value:
printf("%zu\n", sizeof(int)); // most often 4
printf("%zu\n", sizeof(3.14)); // 8, because the literal is a double
Precedence and associativity
When an expression mixes operators, C needs a rule to know what binds tighter. That rule is operator precedence1: high-precedence operators group before low-precedence ones. 2 + 3 * 4 is 2 + (3 * 4) = 14, not 20, because * binds tighter than +.
The practical guidance is short: you cannot reliably memorize the full table, and neither can most working C programmers. Write parentheses to say what you mean:
int x = (a + b) * c; // clear
int y = a + b * c; // correct, but you have to think about it
When operands of the same precedence appear together, order is decided by associativity (left-to-right for arithmetic). The one surprising case is assignment, which is right-to-left: a = b = 5 assigns 5 to b and then to a.
Two more notes worth engraving. Integer division and remainder follow their own rules covered in the data types post. And dangerous-looking expressions like x++ + x++ are undefined behavior: C does not promise any result when you read and modify the same variable more than once in an expression, so never write them.
The big picture
Arithmetic does math, assignment stores results (with handy +=-style shorthand), relational operators produce true/false, logical operators combine them with short-circuiting, bitwise operators touch raw bits, and the ternary operator is a one-line branch. Precedence decides grouping, and parentheses are free insurance. With these, you can write any calculation; the next two posts show how to decide which calculation runs. That is conditionals.
Footnotes
/sponsor
Enjoyed this post? You can sponsor me and this site.