We’re Officially Live β€” Lifetime Founding Membership Available for a Limited Time
Free preview

Operators

Everything between the variables: the symbols that combine, compare, and change values. Learn the four families and the precedence rules that bite.

20 min read

In this lesson:


Four families of operators

Operators are the glue between variables. C has many, but you can group the everyday ones into four families:

Family Operators What they produce
Arithmetic + - * / % A number
Relational == != < > <= >= A truth value (0 or 1)
Logical && || ! A truth value (0 or 1)
Assignment = += -= *= /= %= The value being assigned

That table fits on a Post-it but covers about 90% of expressions you'll ever write.


Arithmetic

The four basic ones are obvious; % (modulo) gives the remainder of integer division:

int a = 17;
int b = 5;
 
int sum   = a + b;     // 22
int diff  = a - b;     // 12
int prod  = a * b;     // 85
int quot  = a / b;     // 3   (integer division β€” truncates)
int rem   = a % b;     // 2   (17 = 3*5 + 2)

Modulo is genuinely useful: n % 2 tells you if n is even or odd, index % BUFFER_SIZE wraps an index around a circular buffer, hour % 12 converts a 24-hour clock to 12-hour.


Relational and the == vs = trap

Relational operators compare two values and produce 1 if the comparison is true, 0 if false:

int x = 5;
int y = 10;
 
x < y       // 1 (true)
x == y      // 0 (false)
x != y      // 1 (true)

The famous beginner bug:

int score = 50;
 
if (score = 100) {              // BUG: '=' assigns, doesn't compare
    printf("Perfect!\n");
}

That code always prints "Perfect!". The = assigns 100 to score and then evaluates to 100, which is non-zero, which counts as "true" in C. To compare, use ==:

if (score == 100) {             // correct: '==' compares
    printf("Perfect!\n");
}

This bug is so common that compilers warn about it (-Wparentheses) and senior C programmers sometimes write the constant on the left, if (100 == score), so a typo (100 = score) becomes a compile error instead of a silent bug.


Logical operators and short-circuiting

&& (AND), || (OR), and ! (NOT) combine truth values:

int age = 25;
int has_ticket = 1;
 
if (age >= 18 && has_ticket) {       // both must be true
    printf("Let them in\n");
}
 
if (age < 18 || !has_ticket) {       // either being true is enough
    printf("Send them away\n");
}

Short-circuit evaluation is the most important property of && and ||:

This is not just a speed optimization. It is your shield against crashes:

// Safe: if 'p' is null, we never dereference it.
if (p != NULL && *p > 0) { ... }
 
// CRASH WAITING: '&' (bitwise AND) does not short-circuit. Both sides get
// evaluated, so *p runs even when p is NULL.
if (p != NULL & *p > 0) { ... }

We will use this pattern constantly throughout the course.


Assignment, compound assignment, and increment

= is assignment, store the right side into the left side:

int count = 0;
count = count + 1;       // works, but verbose

C gives you compact shortcuts for "do something to a variable and store the result back":

count += 1;     // count = count + 1
count -= 2;     // count = count - 2
count *= 3;     // count = count * 3
count /= 4;     // count = count / 4
count %= 5;     // count = count % 5

And for the special case of adding or subtracting 1:

count++;        // post-increment: use the value, then add 1
++count;        // pre-increment: add 1, then use the value
count--;        // post-decrement
--count;        // pre-decrement

For a stand-alone statement like count++;, post and pre are identical in effect. The difference matters when you embed them inside a larger expression, we'll come back to this in the Loops lesson.


Precedence, the order C applies operators

When an expression mixes operators, C applies them in a fixed order (precedence) you don't have to memorize as long as you reach for parentheses:

int result = 2 + 3 * 4;          // 14, not 20: * happens before +
int result2 = (2 + 3) * 4;       // 20: parens force the addition first

A short cheat sheet for the families you've met:

Highest precedence
─────────────────────────────
  !  (unary NOT)
  *  /  %
  +  -
  <  <=  >  >=
  ==  !=
  &&
  ||
  =  +=  -=  *=  /=  %=
─────────────────────────────
Lowest precedence

So an expression like a == b && c < d parses as (a == b) && (c < d), which is what you wanted. But:

if (x & 0x01 == 0)               // BUG: == has higher precedence than &

parses as x & (0x01 == 0), almost certainly not what was intended. When in doubt, parenthesize. It costs you nothing and removes ambiguity.


Gotchas


TL;DR

This is just the start

Sign up free to track progress on this lesson, get coding problems with the Run button, and unlock the full interview Q&A.

More in Programming Fundamentals

What Is a Program?Variables & Data Types
Input & Output
Conditionals
The switch Statement
while & do-while Loops