Operators & Expressions

Scope: Operators are the verbs of a program — they combine values into new values. This lesson covers the arithmetic, assignment, comparison, logical, bitwise and ternary operators, and the rules that decide evaluation order.

Expressions

An expression is any combination of values, variables and operators that evaluates to a single value. Expressions appear everywhere: on the right side of assignments, inside conditions, and as function arguments.

int total = 3 + 4 * 2;      // one expression; evaluates to 11
bool big = total > 10;      // another expression; evaluates to true

Each operand has a type, and the result type is decided by the operands — an operation on two int values yields an int.

Arithmetic

The five arithmetic operators cover the basics. Watch the two forms of division: on integers, / drops the remainder, and % gives it back.

int a = 7 + 3;     // 10  addition
int b = 7 - 3;     // 4   subtraction
int c = 7 * 3;     // 21  multiplication
int d = 7 / 3;     // 2   integer division: remainder dropped
int e = 7 % 3;     // 1   modulo: the remainder

Mixing an integer with a double promotes the integer to double before the operation, giving the decimal answer:

double half = 7 / 2.0;   // 3.5 — the 2.0 forces floating-point division
double bad  = 7 / 2;     // 3.0 — integer division happens first!

The division-by-zero trap is real: integer division by zero crashes the program, and floating division by zero yields infinity or silence depending on the hardware. Guard your denominators.

Assignment

The single = stores a value into a variable. Compound operators combine arithmetic with assignment — x += 5 means x = x + 5 — and are preferred because they are shorter and clearer.

int x = 10;
x += 5;      // x is now 15
x -= 3;      // 12
x *= 2;      // 24
x /= 4;      // 6
x %= 4;      // 2

Assignment is an expression: it produces the assigned value, so a = b = 0 assigns zero to both. Avoid this style when it hurts readability.

Increment & Decrement

++ adds one, -- subtracts one. The prefix form (++x) increments first, then yields the new value; the postfix form (x++) yields the old value, then increments.

int n = 5;
int pre  = ++n;    // n is 6, pre is 6   (increment, then read)
int post = n++;    // n is 7, post is 6  (read old value, then increment)

In loops the difference rarely matters; inside larger expressions it is a classic source of bugs. Prefer ++x as a default — it is also slightly more efficient for complex types.

Comparison

Comparison operators produce a bool. The most common beginner mistake is using one equals (=) where two are needed (==).

int age = 20;
bool isAdult = age >= 18;    // true
bool isTeen  = age > 13 && age < 20;   // false (age is 20)
bool equal   = age == 20;    // true — note the double equals
bool notEq   = age != 21;    // true

Logical

The logical operators combine truth values: && (and), || (or), ! (not). They use short-circuit evaluation: the right side runs only if the left side does not already decide the answer.

bool sunny = true;
bool warm  = false;
bool picnic = sunny && warm;   // false — both must be true
bool outside = sunny || warm;  // true — one is enough
bool stayIn   = !sunny;        // false — negation

Short-circuiting is a safety tool: denominator != 0 && value / denominator > 1 never divides by zero, because the division is skipped when the left side is false.

Bitwise

Bitwise operators work on the individual bits of integers: & (and), | (or), ^ (xor), ~ (not), << (shift left), >> (shift right). They are the language of flags and low-level protocols.

int flags = 0b1100;        // 12 in binary
int mask  = 0b1010;        // 10
int both  = flags & mask;  // 0b1000 = 8   (bits set in both)
int either= flags | mask;  // 0b1110 = 14  (bits set in either)
int xored = flags ^ mask;  // 0b0110 = 6   (bits that differ)
int moved = flags << 1;    // 0b11000 = 24 (shift left one bit)

Shifting left doubles a value; shifting right halves it. You rarely need bitwise math in daily application code, but you will need it in embedded systems, file formats and cryptographic code.

Ternary

The ternary operator cond ? a : b is a compact if/else that produces a value: a when the condition is true, otherwise b.

int age = 20;
std::string label = (age >= 18) ? "Adult" : "Minor";

Use it only for short, obvious choices. If the branches are long or nested, an ordinary if/else reads better.

Precedence

Operators have a built-in precedence (priority) and associativity that decide evaluation order. Multiplication binds tighter than addition, just like in school:

int x = 2 + 3 * 4;    // 14, not 20 — multiplication first
int y = (2 + 3) * 4;  // 20 — parentheses override precedence

The rule every professional follows: do not rely on remembering the table. Add parentheses whenever the meaning is not instantly obvious — they cost nothing and prevent real bugs.

Practice

Write short programs that print the answers so you can verify each one:

  1. Compute 17 % 5 and 17 / 5. Explain both results aloud.
  2. Write bool isLeap = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); and test 2000, 1900, 2024.
  3. Show that !a || b differs from !(a || b) for two sample booleans.
  4. Using only << and |, build the value 0b1010 from 1.