Lesson 28 min read

Operators & Expressions

Every tool in the shed β€” including the power tools

C's Toolbox

If Python gives you a neat little toolkit, C gives you the entire hardware store. You get the usual arithmetic and comparison operators, but you also get direct access to bitwise operators β€” tools that let you flip individual bits in memory. This is why C is the language of operating systems and embedded devices.

Let's go through each category, from the everyday hammers to the power tools.

Arithmetic Operators

The basics: + (add), - (subtract), * (multiply), / (divide), and % (modulo β€” remainder after division). These work just like you'd expect, with one important catch...

Arithmetic β€” Watch the Integer Division!

#include <stdio.h>
int main() {
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); // Surprise!
printf("%d %% %d = %d\n", a, b, a % b);
// The fix: cast to double
printf("%d / %d = %.2f\n", a, b, (double)a / b);
return 0;
}
Output
17 + 5 = 22
17 - 5 = 12
17 * 5 = 85
17 / 5 = 3
17 % 5 = 2
17 / 5 = 3.40
Note: Integer division truncates! When both operands are integers, / throws away the decimal part. 5 / 2 gives 2, not 2.5. If you need the decimal, cast at least one operand to double: (double)5 / 2 gives 2.5.

Relational & Logical Operators

Relational operators compare two values and return 1 (true) or 0 (false). Logical operators combine conditions. Remember β€” in C, there's no True/False keywords by default, just 1 and 0.

Comparisons and Logic

#include <stdio.h>
int main() {
int x = 10, y = 20;
// Relational operators
printf("%d == %d : %d\n", x, y, x == y);
printf("%d != %d : %d\n", x, y, x != y);
printf("%d > %d : %d\n", x, y, x > y);
printf("%d <= %d : %d\n", x, y, x <= y);
// Logical operators
int age = 25;
int has_id = 1;
printf("Can enter: %d\n", age >= 21 && has_id);
printf("Is teen or senior: %d\n", age < 20 || age > 60);
printf("NOT has_id: %d\n", !has_id);
return 0;
}
Output
10 == 20 : 0
10 != 20 : 1
10 >  20 : 0
10 <= 20 : 1
Can enter: 1
Is teen or senior: 0
NOT has_id: 0

Increment & Decrement

The ++ and -- operators add or subtract 1. But where you place them matters: ++x (prefix) increments before using the value, while x++ (postfix) uses the value then increments. This is a classic C interview question.

Prefix vs Postfix

#include <stdio.h>
int main() {
int a = 5, b = 5;
printf("a++: %d\n", a++); // Prints 5, THEN a becomes 6
printf("a now: %d\n", a);
printf("++b: %d\n", ++b); // b becomes 6, THEN prints 6
printf("b now: %d\n", b);
return 0;
}
Output
a++: 5
a now: 6
++b: 6
b now: 6

Assignment Operators

Shorthand for updating a variable: +=, -=, *=, /=, %=, and the bitwise variants &=, |=, ^=, <<=, >>=.

Compound Assignment

#include <stdio.h>
int main() {
int score = 100;
score += 50; // score = score + 50
printf("After += 50: %d\n", score);
score -= 30; // score = score - 30
printf("After -= 30: %d\n", score);
score *= 2; // score = score * 2
printf("After *= 2: %d\n", score);
score /= 3; // score = score / 3 (integer division)
printf("After /= 3: %d\n", score);
score %= 10; // score = score % 10
printf("After %%= 10: %d\n", score);
return 0;
}
Output
After += 50: 150
After -= 30: 120
After *= 2:  240
After /= 3:  80
After %= 10: 0

Bitwise Operators β€” The Power Tools

These operators work on individual bits β€” the 0s and 1s that make up every number in memory. They're essential for systems programming, embedded devices, and performance-critical code.

  • & (AND) β€” Both bits must be 1
  • | (OR) β€” At least one bit must be 1
  • ^ (XOR) β€” Exactly one bit must be 1
  • ~ (NOT) β€” Flip all bits
  • << (left shift) β€” Shift bits left (multiply by 2)
  • >> (right shift) β€” Shift bits right (divide by 2)

Bitwise Operations

#include <stdio.h>
int main() {
unsigned char a = 0b11001010; // 202 in decimal
unsigned char b = 0b10110101; // 181 in decimal
printf("a & b = %d\n", a & b); // AND
printf("a | b = %d\n", a | b); // OR
printf("a ^ b = %d\n", a ^ b); // XOR
printf("~a = %d\n", (unsigned char)~a); // NOT
// Shifting = fast multiply/divide by powers of 2
int x = 5;
printf("%d << 1 = %d\n", x, x << 1); // 5 * 2 = 10
printf("%d << 3 = %d\n", x, x << 3); // 5 * 8 = 40
printf("%d >> 1 = %d\n", x, x >> 1); // 5 / 2 = 2
return 0;
}
Output
a & b  = 128
a | b  = 255
a ^ b  = 127
~a     = 53
5 << 1 = 10
5 << 3 = 40
5 >> 1 = 2
Note: Operator precedence can bite you. For example, x & 1 == 0 is not (x & 1) == 0 β€” it's actually x & (1 == 0) because == has higher precedence than &. When in doubt, use parentheses. Your future self will thank you.
Challenge

Quick check

What does 7 / 2 evaluate to in C (both operands are int)?
← Variables & Data TypesInput & Output β†’