Operators
Reviewed & published by Brayan K
By the end of this lesson you'll be able to do maths, compare values, combine true/false conditions, and understand the order C++ evaluates an expression — the toolkit behind every calculation and decision your programs make.
Part of the free C++ course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.
What You'll Learn
- Do maths with + - * / % and understand integer division
- Compare values with == != and the relational operators
- Combine conditions with && || ! and how short-circuiting works
- Update variables with = and the compound operators (+= -= *= /=)
- Add or subtract 1 with pre/post increment (++x vs x++)
- Read bitwise operators (& | ^ ~ << >>) and operator precedence
💡 Real-World Analogy
Think of operators as the buttons on a calculator. The number keys are your variables; the +, -, × and ÷ keys are the arithmetic operators. But C++ has extra buttons a basic calculator lacks: a "compare" button that answers yes or no (>, ==), "and / or" buttons that fold several yes/no answers into one decision, and a "%" button that hands you the remainder. Learn what each button does and in what order the calculator presses them, and you can express any calculation or rule.
1. Arithmetic Operators
The five arithmetic operators are + add, - subtract, * multiply, / divide, and % modulo (remainder). The one that surprises every beginner is /: when both sides are whole numbers, C++ does integer division and silently throws away the decimal part, so 17 / 5 is 3, not 3.4. Make one side a decimal (17.0) to get a real result. Read this worked example and run it.
#include <iostream>
using namespace std;
int main() {
// The arithmetic operators are a calculator built into C++.
int a = 17, b = 5;
cout << a << " + " << b << " = " << (a + b) << endl; // 22
cout << a << " - " << b << " = " << (a - b) << endl; // 12
cout << a << " * " << b << " = " << (a * b) << endl; // 85
// / between two ints does INTEGER division: it throws away the remainder.
cout << a << " / " << b << " = " << (a / b) << endl; // 3 (not 3.4!)
// % (modulo) gives the remainder that division left behind.
cout << a << " % " << b << " = " << (a % b) << endl; // 2
// Make ONE side a double and you get a real decimal result.
cout << "17.0 / 5 = " << (17.0 / 5) << endl; // 3.4
return 0;
}
// ✅ Expected output:
// 17 + 5 = 22
// 17 - 5 = 12
// 17 * 5 = 85
// 17 / 5 = 3
// 17 % 5 = 2
// 17.0 / 5 = 3.4Your turn. % and integer division together let you split a total into parts — here, seconds into hours, minutes and seconds. Fill in the three blanks marked ___, then run it.
#include <iostream>
using namespace std;
int main() {
// 🎯 YOUR TURN — replace each ___ then press "Try it Yourself".
// Goal: turn a number of seconds into hours, minutes and seconds.
int totalSeconds = 3661;
// 1) Whole hours = totalSeconds divided by 3600 (integer division)
int hours = ___; // 👉 totalSeconds / 3600
// 2) Leftover minutes: take the remainder of an hour, then / 60
int minutes = (totalSeconds % 3600) / ___; // 👉 60
// 3) Leftover seconds = the remainder when divided by 60
int seconds = totalSeconds % ___; // 👉 60
cout << totalSeconds << "s = "
<< hours << "h " << minutes << "m " << seconds << "s" << endl;
// ✅ Expected output: 3661s = 1h 1m 1s
return 0;
}2. Comparison & Logical Operators
Comparison operators ask a yes/no question and hand back a bool — cout prints that as 1 for true or 0 for false. The six are == equal, != not equal, >, <, >= and <=. Logical operators then combine those answers: && (AND) is true only when both sides are true, || (OR) is true when at least one is, and ! (NOT) flips a value. C++ is also short-circuit: with && a false left side skips the right entirely, which is how you write safe guards.
#include <iostream>
using namespace std;
int main() {
int age = 20;
double gpa = 3.7;
bool hasPermission = true;
// Comparison operators ask a yes/no question -> they return a bool.
// cout prints a bool as 1 (true) or 0 (false).
cout << "age == 20: " << (age == 20) << endl; // 1 (true)
cout << "age != 18: " << (age != 18) << endl; // 1 (true)
cout << "age > 21: " << (age > 21) << endl; // 0 (false)
cout << "age <= 20: " << (age <= 20) << endl; // 1 (true)
// Logical operators combine those yes/no answers.
// && (AND) is true only when BOTH sides are true.
bool canEnroll = (age >= 18) && (gpa >= 3.0);
cout << "canEnroll: " << canEnroll << endl; // 1
// || (OR) is true when AT LEAST ONE side is true.
bool hasAccess = hasPermission || (age >= 21);
cout << "hasAccess: " << hasAccess << endl; // 1
// ! (NOT) flips true<->false.
bool isMinor = !(age >= 18);
cout << "isMinor: " << isMinor << endl; // 0
// Short-circuit: with &&, if the left side is false C++ never even
// checks the right side (the answer is already false). With ||, a true
// left side skips the right. This is what lets you write safe checks like:
// (count != 0) && (total / count > 5) // the divide only runs if count != 0
return 0;
}
// ✅ Expected output:
// age == 20: 1
// age != 18: 1
// age > 21: 0
// age <= 20: 1
// canEnroll: 1
// hasAccess: 1
// isMinor: 0Now you try. A ride is allowed if you are tall enough and (old enough or with a guardian). Pick the right operator for each blank:
#include <iostream>
using namespace std;
int main() {
// 🎯 YOUR TURN — a theme-park ride lets you on if you are tall enough
// AND (an adult OR with a guardian). Fill the blanks.
int height = 140; // cm
int age = 9;
bool withGuardian = true;
// 1) Tall enough means height of 120 cm or more
bool tallEnough = height ___ 120; // 👉 use >=
// 2) Allowed if tall enough AND (16 or older OR with a guardian)
bool canRide = tallEnough ___ (age >= 16 || withGuardian); // 👉 use &&
cout << "Tall enough: " << tallEnough << endl;
cout << "Can ride: " << canRide << endl;
// ✅ Expected output:
// Tall enough: 1
// Can ride: 1
return 0;
}3. Increment, Decrement & Compound Assignment
Adding or subtracting 1 is so common it has its own operators: ++ and --. Where you put them matters. Post (x++) uses the old value then adds 1; pre (++x) adds 1 then uses the new value. The compound operators (+=, -=, *=, /=, %=) are shorthand: score += 25 means exactly score = score + 25, just shorter and clearer.
#include <iostream>
using namespace std;
int main() {
// POST-increment (x++): use the OLD value first, THEN add 1.
int x = 5;
cout << "x++ gives " << x++ << endl; // prints 5
cout << "x is now " << x << endl; // 6
// PRE-increment (++x): add 1 FIRST, then use the new value.
cout << "++x gives " << ++x << endl; // prints 7
cout << "x is now " << x << endl; // 7
// -- works the same way, but subtracts 1.
int y = 10;
cout << "y-- gives " << y-- << endl; // prints 10, y becomes 9
// Compound assignment = "do the maths and store it back" in one step.
int score = 100;
score += 25; // same as: score = score + 25
cout << "after += 25: " << score << endl; // 125
score -= 10; // score = score - 10
cout << "after -= 10: " << score << endl; // 115
score *= 2; // score = score * 2
cout << "after *= 2: " << score << endl; // 230
score /= 5; // score = score / 5
cout << "after /= 5: " << score << endl; // 46
return 0;
}
// ✅ Expected output:
// x++ gives 5
// x is now 6
// ++x gives 7
// x is now 7
// y-- gives 10
// after += 25: 125
// after -= 10: 115
// after *= 2: 230
// after /= 5: 464. Bitwise Operators
Numbers are stored as bits — strings of 0s and 1s — and the bitwise operators work on those bits directly. & (AND), | (OR), ^ (XOR) and ~ (NOT) combine bits, while the shift operators << and >> slide all the bits left or right. A handy shortcut: shifting left by one (x << 1) doubles a number, and shifting right halves it. You won't reach for these every day, but you'll meet them in flags, permissions and performance code.
#include <iostream>
using namespace std;
int main() {
// Bitwise operators work on the individual 0/1 bits of a number.
// 12 is 1100 in binary, 10 is 1010.
int a = 12, b = 10;
cout << "a & b = " << (a & b) << endl; // 8 AND: 1 only where BOTH bits are 1 (1000)
cout << "a | b = " << (a | b) << endl; // 14 OR: 1 where EITHER bit is 1 (1110)
cout << "a ^ b = " << (a ^ b) << endl; // 6 XOR: 1 where the bits DIFFER (0110)
cout << "~a = " << (~a) << endl; // -13 NOT: flips every bit
// Shifts move the bits left or right.
cout << "5 << 1 = " << (5 << 1) << endl; // 10 shift left -> multiply by 2
cout << "20 >> 2 = " << (20 >> 2) << endl;// 5 shift right -> divide by 2 (twice)
return 0;
}
// ✅ Expected output:
// a & b = 8
// a | b = 14
// a ^ b = 6
// ~a = -13
// 5 << 1 = 10
// 20 >> 2 = 55. Operator Precedence
Precedence is the order C++ applies operators when you don't use parentheses — exactly like "BODMAS" from school. * and / run before + and -, so 2 + 3 * 4 is 14, not 20. Comparisons run before &&, which runs before ||, and assignment (=) runs last. The golden rule: when an expression isn't obvious, add parentheses. They cost nothing and remove all doubt.
#include <iostream>
using namespace std;
int main() {
// Like school maths, C++ does * and / before + and -.
cout << (2 + 3 * 4) << endl; // 14, NOT 20 (3*4 happens first)
// Parentheses force the order you want.
cout << ((2 + 3) * 4) << endl; // 20
// Comparisons happen before && and ||, so this reads naturally:
int age = 20;
bool ok = age > 18 && age < 65; // (age>18) && (age<65)
cout << "ok: " << ok << endl; // 1
// When unsure, ADD PARENTHESES. They cost nothing and remove all doubt.
return 0;
}
// ✅ Expected output:
// 14
// 20
// ok: 1Pro Tips
- 💡 Reach for parentheses: (a + b) * c is clearer than relying on precedence, and the compiler doesn't mind.
- 💡 Use % for patterns: n % 2 == 0 tests even/odd, and i % len wraps an index back round.
- 💡 The ternary ? : is a mini if/else: string s = (n > 0) ? "pos" : "neg"; picks a value in one line.
- 💡 Avoid divide-by-zero with short-circuit: (count != 0) && (total / count > 5) never divides when count is 0.
Common Errors (and the fix)
- = instead of == in a condition: if (x = 5) assigns 5 to x and is always true. To compare, use if (x == 5). Many compilers warn with "suggest parentheses around assignment used as truth value".
- Integer division surprise: int r = 7 / 2; gives 3, not 3.5. Make a side a double: 7.0 / 2 or (double)7 / 2.
- Pre vs post increment in an expression: arr[i++] and arr[++i] use different indexes. On its own line they're identical; inside a bigger expression the position changes the result.
- Precedence assumption: 2 + 3 * 4 is 14 because * binds tighter than +. Write (2 + 3) * 4 if you meant 20.
- Division by zero: dividing an integer by 0 is undefined behaviour and may crash. Guard the divisor first: if (count != 0) ....
📋 Quick Reference: Operator Precedence (high → low)
| Level | Operators | Meaning |
|---|---|---|
| 1 (highest) | () ++ -- ! ~ | Grouping, increment/decrement, logical & bitwise NOT |
| 2 | * / % | Multiply, divide, modulo |
| 3 | + - | Add, subtract |
| 4 | << >> | Bit shift left / right |
| 5 | < <= > >= | Relational comparisons |
| 6 | == != | Equality |
| 7 | & ^ | | Bitwise AND, XOR, OR |
| 8 | && || | Logical AND, then OR |
| 9 (lowest) | ?: = += -= *= /= %= | Ternary and assignment |
When two operators share a level they're read left to right (assignment is the exception — it reads right to left). Don't memorise the whole table; just remember "maths before comparisons before &&/||, and parentheses beat everything."
Mini-Challenge: Change-Making Machine
No blanks this time — just a brief and an outline to keep you on track. Use integer division and % to split a pence total into pounds and leftover pence, then run it and check your output against the comment.
#include <iostream>
using namespace std;
int main() {
// 🎯 MINI-CHALLENGE: Change-making machine
// A till has 287 pence. Work out how to give it as coins.
// 1. Make an int "pence" set to 287.
// 2. pounds = whole pounds (pence / 100)
// 3. leftover = pence left over (pence % 100)
// 4. Print: "287p = 2 pounds and 87p"
// 5. BONUS: is the leftover an even number? (leftover % 2 == 0)
//
// ✅ Expected output:
// 287p = 2 pounds and 87p
// Leftover is even: 0
// your code here
return 0;
}🎉 Lesson Complete
- ✅ Arithmetic + - * / % — and / between two ints truncates
- ✅ Comparisons return a bool (printed as 1/0): == != > < >= <=
- ✅ Logical && || ! combine conditions and short-circuit
- ✅ ++ -- add/subtract 1; pre vs post changes what the expression returns
- ✅ Compound += -= *= /= %= update a variable in one step
- ✅ Bitwise & | ^ ~ << >> work on individual bits
- ✅ Precedence decides who goes first — when in doubt, add parentheses
Practice quiz
What does 17 % 5 evaluate to?
- 3
- 3.4
- 2
- 1
Answer: 2. % is modulo (remainder): 17 divided by 5 is 3 remainder 2.
What does the int expression 17 / 5 evaluate to?
- 3
- 3.4
- 4
- 2
Answer: 3. Both operands are int, so integer division drops the remainder, giving 3.
What value do comparison operators like == and > return?
- An int count
- A string
- A char
- A bool (printed as 1 or 0)
Answer: A bool (printed as 1 or 0). Comparisons return a bool, which cout prints as 1 (true) or 0 (false).
When is the && (AND) operator true?
- When at least one side is true
- Only when both sides are true
- When both sides are false
- Always
Answer: Only when both sides are true. && is true only when BOTH operands are true.
What does short-circuit evaluation mean for &&?
- If the left side is false, the right side is skipped
- Both sides always run
- The right side runs first
- It throws if the left is false
Answer: If the left side is false, the right side is skipped. With &&, a false left side makes the result false, so the right side is never evaluated.
What is the difference between x++ and ++x?
- No difference ever
- x++ returns the new value, ++x the old
- x++ returns the old value, ++x returns the new value
- ++x subtracts 1
Answer: x++ returns the old value, ++x returns the new value. Post-increment x++ yields the old value then adds 1; pre-increment ++x adds 1 then yields the new value.
What is 'score += 25;' shorthand for?
- score = 25
- score = score + 25
- score = score * 25
- score == 25
Answer: score = score + 25. Compound assignment += means score = score + 25.
What does 5 << 1 evaluate to?
- 6
- 2
- 25
- 10
Answer: 10. Shifting left by 1 doubles the value: 5 << 1 = 10.
Because of precedence, what does 2 + 3 * 4 evaluate to?
- 20
- 14
- 24
- 9
Answer: 14. * binds tighter than +, so 3*4 happens first: 2 + 12 = 14.
What does writing 'if (x = 5)' actually do?
- Compares x with 5
- Causes a runtime crash
- Assigns 5 to x and is always true
- Sets x to 0
Answer: Assigns 5 to x and is always true. A single = assigns; if (x = 5) stores 5 in x and the non-zero value is always true. Use == to compare.
Continue this course
- Previous: Input & Output (cin & cout)
- Next: Control Flow — Make decisions with if, else if, else, and switch statements
- Quick reference: C++ cheat sheet
Frequently asked questions
Why did 7 / 2 give me 3 instead of 3.5?
Both numbers are integers, so C++ uses integer division and throws away the remainder. Make at least one side a double — 7.0 / 2 or (double)7 / 2 — to get 3.5.
What is the difference between = and ==?
A single = assigns a value (x = 5 puts 5 into x). A double == compares two values and returns true or false. Writing if (x = 5) assigns instead of comparing and is always true, which is a classic bug.
When should I use ++x instead of x++?
Both add 1 to x. The difference is only the value the expression hands back: ++x gives the new value, x++ gives the old value first. On its own line they behave identically; the choice only matters when you use the result inside a bigger expression.
What does short-circuit evaluation mean?
With &&, if the left side is false C++ skips the right side because the result is already false. With ||, a true left side skips the right. This lets you guard risky code, e.g. (count != 0) && (total / count > 5) never divides by zero.
Do I really need bitwise operators as a beginner?
Rarely day to day, but they appear in flags, permissions, low-level code, and performance tricks (x << 1 doubles a number). Knowing & | ^ ~ << >> exist means you will recognise them when you meet them.