Introduction to Operators
Operators are symbols that tell the compiler to perform specific mathematical, relational, or logical operations. C++ provides a rich set of operators to manipulate data and variables, making it a powerful language for both high-level and low-level programming.
Operator
An operator is a symbol that operates on one or more operands to produce a result. Operators can be unary (one operand), binary (two operands), or ternary (three operands).
Expression: a + b where + is the operator
and a, b are operands.
Categories of Operators
Arithmetic
+, -, *, /, %, ++, -- for mathematical calculations
Relational
==, !=, <, >, <=, >= for comparisons
Logical
&&, ||, ! for boolean logic operations
Arithmetic Operators
Arithmetic operators perform mathematical operations on numeric operands. C++ supports all standard arithmetic operations plus increment and decrement.
Basic Arithmetic Operators
#include <iostream>
using namespace std;
int main() {
int a = 17, b = 5;
// Addition
cout << "a + b = " << (a + b) << endl; // 22
// Subtraction
cout << "a - b = " << (a - b) << endl; // 12
// Multiplication
cout << "a * b = " << (a * b) << endl; // 85
// Division (integer division truncates)
cout << "a / b = " << (a / b) << endl; // 3 (not 3.4)
// Modulus (remainder)
cout << "a % b = " << (a % b) << endl; // 2
// Floating-point division
double x = 17.0, y = 5.0;
cout << "x / y = " << (x / y) << endl; // 3.4
return 0;
}
Increment and Decrement Operators
#include <iostream>
using namespace std;
int main() {
int a = 5;
// Pre-increment: increment first, then use
cout << "++a = " << ++a << endl; // 6 (a is now 6)
// Post-increment: use first, then increment
cout << "a++ = " << a++ << endl; // 6 (a becomes 7 after)
cout << "a = " << a << endl; // 7
// Pre-decrement: decrement first, then use
cout << "--a = " << --a << endl; // 6 (a is now 6)
// Post-decrement: use first, then decrement
cout << "a-- = " << a-- << endl; // 6 (a becomes 5 after)
cout << "a = " << a << endl; // 5
// Common usage in loops
for (int i = 0; i < 5; i++) {
cout << i << " "; // 0 1 2 3 4
}
return 0;
}
(double)a / b
Arithmetic Operators Table
| Operator | Name | Example | Result (a=10, b=3) |
|---|---|---|---|
+ |
Addition | a + b | 13 |
- |
Subtraction | a - b | 7 |
* |
Multiplication | a * b | 30 |
/ |
Division | a / b | 3 |
% |
Modulus | a % b | 1 |
++ |
Increment | a++ or ++a | 11 |
-- |
Decrement | a-- or --a | 9 |
Practice Questions
Task: Write a program to calculate the average of 3 numbers.
Show Solution
#include <iostream>
using namespace std;
int main() {
double a = 10, b = 20, c = 30;
double average = (a + b + c) / 3;
cout << "Average: " << average << endl; // 20
return 0;
}
Task: What is the output of this code?
int x = 5;
int y = x++ + ++x;
cout << x << " " << y;
Show Solution
// Output: 7 12
// Explanation:
// x++ returns 5, then x becomes 6
// ++x increments x to 7, then returns 7
// y = 5 + 7 = 12
// Final: x = 7, y = 12
// Note: This behavior can be undefined in some cases.
// Avoid using multiple increments in one expression!
Relational Operators
Relational operators compare two values and return a boolean result (true
or false). They are essential for making decisions in control structures.
#include <iostream>
using namespace std;
int main() {
int a = 10, b = 20;
// Equal to
cout << "a == b: " << (a == b) << endl; // 0 (false)
// Not equal to
cout << "a != b: " << (a != b) << endl; // 1 (true)
// Greater than
cout << "a > b: " << (a > b) << endl; // 0 (false)
// Less than
cout << "a < b: " << (a < b) << endl; // 1 (true)
// Greater than or equal to
cout << "a >= b: " << (a >= b) << endl; // 0 (false)
// Less than or equal to
cout << "a <= b: " << (a <= b) << endl; // 1 (true)
// Using with boolalpha for readable output
cout << boolalpha;
cout << "a < b: " << (a < b) << endl; // true
return 0;
}
Three-Way Comparison (C++20)
// C++20 introduced the spaceship operator <=>
#include <iostream>
#include <compare>
using namespace std;
int main() {
int a = 10, b = 20;
// Returns: negative if a < b, zero if a == b, positive if a > b
auto result = a <=> b;
if (result < 0)
cout << "a is less than b" << endl;
else if (result > 0)
cout << "a is greater than b" << endl;
else
cout << "a equals b" << endl;
return 0;
}
Relational Operators Table
| Operator | Name | Example | Result (a=10, b=20) |
|---|---|---|---|
== |
Equal to | a == b | false |
!= |
Not equal to | a != b | true |
> |
Greater than | a > b | false |
< |
Less than | a < b | true |
>= |
Greater or equal | a >= b | false |
<= |
Less or equal | a <= b | true |
<=> |
Three-way (C++20) | a <=> b | negative |
Logical Operators
Logical operators combine boolean expressions. They are used to create complex conditions in if statements, loops, and other control structures.
#include <iostream>
using namespace std;
int main() {
bool a = true, b = false;
cout << boolalpha; // Print true/false instead of 1/0
// Logical AND: true only if BOTH are true
cout << "a && b: " << (a && b) << endl; // false
cout << "a && a: " << (a && a) << endl; // true
// Logical OR: true if AT LEAST ONE is true
cout << "a || b: " << (a || b) << endl; // true
cout << "b || b: " << (b || b) << endl; // false
// Logical NOT: inverts the value
cout << "!a: " << !a << endl; // false
cout << "!b: " << !b << endl; // true
// Practical example
int age = 25;
bool hasLicense = true;
if (age >= 18 && hasLicense) {
cout << "Can drive!" << endl;
}
return 0;
}
Short-Circuit Evaluation
#include <iostream>
using namespace std;
int main() {
// Short-circuit AND: if first is false, second is NOT evaluated
int x = 0;
if (x != 0 && 10/x > 1) { // 10/x never executes (would cause division by zero!)
cout << "Condition met" << endl;
}
// Short-circuit OR: if first is true, second is NOT evaluated
bool found = true;
if (found || expensiveSearch()) { // expensiveSearch() never runs
cout << "Found!" << endl;
}
// Demonstration
cout << "Testing short-circuit:" << endl;
bool result = false && (cout << "This won't print\n", true);
result = true || (cout << "This won't print either\n", true);
result = true && (cout << "This WILL print\n", true);
result = false || (cout << "This WILL print too\n", true);
return 0;
}
bool expensiveSearch() {
cout << "Expensive search running..." << endl;
return true;
}
Truth Tables
AND (&&)
| A | B | A && B |
|---|---|---|
| T | T | T |
| T | F | F |
| F | T | F |
| F | F | F |
OR (||)
| A | B | A || B |
|---|---|---|
| T | T | T |
| T | F | T |
| F | T | T |
| F | F | F |
NOT (!)
| A | !A |
|---|---|
| T | F |
| F | T |
Bitwise Operators
Bitwise operators work at the binary level, manipulating individual bits. They are powerful tools for low-level programming, flags, and optimization.
#include <iostream>
#include <bitset>
using namespace std;
int main() {
unsigned int a = 5; // Binary: 0101
unsigned int b = 3; // Binary: 0011
cout << "a = " << bitset<4>(a) << " (" << a << ")" << endl;
cout << "b = " << bitset<4>(b) << " (" << b << ")" << endl;
cout << endl;
// Bitwise AND: 1 if both bits are 1
cout << "a & b = " << bitset<4>(a & b) << " (" << (a & b) << ")" << endl;
// 0101 & 0011 = 0001 (1)
// Bitwise OR: 1 if at least one bit is 1
cout << "a | b = " << bitset<4>(a | b) << " (" << (a | b) << ")" << endl;
// 0101 | 0011 = 0111 (7)
// Bitwise XOR: 1 if bits are different
cout << "a ^ b = " << bitset<4>(a ^ b) << " (" << (a ^ b) << ")" << endl;
// 0101 ^ 0011 = 0110 (6)
// Bitwise NOT: inverts all bits
cout << "~a = " << bitset<32>(~a) << " (" << (~a) << ")" << endl;
// ~0101 = 1111...1010
// Left shift: shifts bits left (multiply by 2^n)
cout << "a << 1 = " << bitset<4>(a << 1) << " (" << (a << 1) << ")" << endl;
// 0101 << 1 = 1010 (10)
// Right shift: shifts bits right (divide by 2^n)
cout << "a >> 1 = " << bitset<4>(a >> 1) << " (" << (a >> 1) << ")" << endl;
// 0101 >> 1 = 0010 (2)
return 0;
}
Practical Bitwise Applications
#include <iostream>
using namespace std;
int main() {
// 1. Check if number is even or odd
int num = 7;
if (num & 1) {
cout << num << " is odd" << endl;
} else {
cout << num << " is even" << endl;
}
// 2. Multiply/Divide by powers of 2 (faster than * or /)
int x = 5;
cout << x << " * 8 = " << (x << 3) << endl; // 40
cout << x << " / 2 = " << (x >> 1) << endl; // 2
// 3. Swap without temp variable (using XOR)
int a = 10, b = 20;
cout << "Before swap: a=" << a << ", b=" << b << endl;
a = a ^ b;
b = a ^ b; // b = (a^b) ^ b = a
a = a ^ b; // a = (a^b) ^ a = b
cout << "After swap: a=" << a << ", b=" << b << endl;
// 4. Set, clear, and toggle bits (flags)
unsigned int flags = 0;
// Set bit 2 (turn ON)
flags |= (1 << 2); // flags = 0100 (4)
cout << "After setting bit 2: " << flags << endl;
// Clear bit 2 (turn OFF)
flags &= ~(1 << 2); // flags = 0000 (0)
cout << "After clearing bit 2: " << flags << endl;
// Toggle bit 3
flags ^= (1 << 3); // flags = 1000 (8)
cout << "After toggling bit 3: " << flags << endl;
// Check if bit is set
if (flags & (1 << 3)) {
cout << "Bit 3 is set" << endl;
}
return 0;
}
Bitwise Operators Table
| Operator | Name | Example | Operation |
|---|---|---|---|
& |
AND | 5 & 3 = 1 | 0101 & 0011 = 0001 |
| |
OR | 5 | 3 = 7 | 0101 | 0011 = 0111 |
^ |
XOR | 5 ^ 3 = 6 | 0101 ^ 0011 = 0110 |
~ |
NOT | ~5 | Inverts all bits |
<< |
Left Shift | 5 << 1 = 10 | 0101 → 1010 |
>> |
Right Shift | 5 >> 1 = 2 | 0101 → 0010 |
Assignment Operators
Assignment operators store values in variables. C++ provides compound assignment operators that combine an arithmetic or bitwise operation with assignment.
#include <iostream>
using namespace std;
int main() {
int a;
// Simple assignment
a = 10;
cout << "a = 10: " << a << endl;
// Add and assign
a += 5; // Same as: a = a + 5
cout << "a += 5: " << a << endl; // 15
// Subtract and assign
a -= 3; // Same as: a = a - 3
cout << "a -= 3: " << a << endl; // 12
// Multiply and assign
a *= 2; // Same as: a = a * 2
cout << "a *= 2: " << a << endl; // 24
// Divide and assign
a /= 4; // Same as: a = a / 4
cout << "a /= 4: " << a << endl; // 6
// Modulus and assign
a %= 4; // Same as: a = a % 4
cout << "a %= 4: " << a << endl; // 2
// Bitwise compound assignments
a = 5;
a &= 3; // a = 5 & 3 = 1
cout << "5 &= 3: " << a << endl;
a = 5;
a |= 3; // a = 5 | 3 = 7
cout << "5 |= 3: " << a << endl;
a = 5;
a ^= 3; // a = 5 ^ 3 = 6
cout << "5 ^= 3: " << a << endl;
a = 8;
a >>= 2; // a = 8 >> 2 = 2
cout << "8 >>= 2: " << a << endl;
a = 2;
a <<= 3; // a = 2 << 3 = 16
cout << "2 <<= 3: " << a << endl;
return 0;
}
Assignment Operators Table
| Operator | Example | Equivalent |
|---|---|---|
= | a = b | a = b |
+= | a += b | a = a + b |
-= | a -= b | a = a - b |
*= | a *= b | a = a * b |
/= | a /= b | a = a / b |
%= | a %= b | a = a % b |
&= | a &= b | a = a & b |
|= | a |= b | a = a | b |
^= | a ^= b | a = a ^ b |
<<= | a <<= b | a = a << b |
>>= | a >>= b | a = a >> b |
Special Operators
C++ includes several special operators for specific purposes like conditional expressions, memory operations, type information, and member access.
Ternary Operator (?:)
#include <iostream>
using namespace std;
int main() {
// Syntax: condition ? value_if_true : value_if_false
int a = 10, b = 20;
// Instead of if-else
int max = (a > b) ? a : b;
cout << "Max: " << max << endl; // 20
// Nested ternary (use sparingly!)
int c = 15;
int largest = (a > b) ? (a > c ? a : c) : (b > c ? b : c);
cout << "Largest: " << largest << endl; // 20
// Ternary with different types
bool isEven = (a % 2 == 0);
cout << a << " is " << (isEven ? "even" : "odd") << endl;
return 0;
}
sizeof Operator
#include <iostream>
using namespace std;
int main() {
// sizeof returns size in bytes
cout << "Size of char: " << sizeof(char) << " byte" << endl; // 1
cout << "Size of int: " << sizeof(int) << " bytes" << endl; // 4
cout << "Size of long: " << sizeof(long) << " bytes" << endl; // 4 or 8
cout << "Size of float: " << sizeof(float) << " bytes" << endl; // 4
cout << "Size of double: " << sizeof(double) << " bytes" << endl; // 8
cout << "Size of bool: " << sizeof(bool) << " byte" << endl; // 1
// sizeof with variables
int arr[10];
cout << "Size of arr: " << sizeof(arr) << " bytes" << endl; // 40
cout << "Array length: " << sizeof(arr)/sizeof(arr[0]) << endl; // 10
// sizeof with expressions (doesn't evaluate!)
int x = 5;
cout << "sizeof(x++): " << sizeof(x++) << endl; // 4
cout << "x is still: " << x << endl; // 5 (not incremented!)
return 0;
}
Comma Operator
#include <iostream>
using namespace std;
int main() {
// Comma evaluates left to right, returns rightmost value
int a = (1, 2, 3); // a = 3
cout << "a = " << a << endl;
// Common use in for loops
for (int i = 0, j = 10; i < j; i++, j--) {
cout << i << " " << j << endl;
}
return 0;
}
Other Special Operators
#include <iostream>
#include <typeinfo>
using namespace std;
int main() {
// Address-of operator (&)
int x = 10;
cout << "Address of x: " << &x << endl;
// Dereference operator (*)
int* ptr = &x;
cout << "Value at ptr: " << *ptr << endl; // 10
// Member access operators (. and ->)
struct Point { int x, y; };
Point p = {3, 4};
Point* pp = &p;
cout << "p.x = " << p.x << endl; // Using .
cout << "pp->x = " << pp->x << endl; // Using ->
// typeid operator
cout << "Type of x: " << typeid(x).name() << endl;
// Scope resolution operator (::)
cout << "Using std::cout" << std::endl;
return 0;
}
Operator Precedence
Operator precedence determines the order in which operators are evaluated. Higher precedence operators are evaluated first. Use parentheses to override precedence and improve code clarity.
#include <iostream>
using namespace std;
int main() {
// Precedence example
int result = 2 + 3 * 4; // 14 (not 20) - * has higher precedence
cout << "2 + 3 * 4 = " << result << endl;
result = (2 + 3) * 4; // 20 - parentheses override
cout << "(2 + 3) * 4 = " << result << endl;
// Associativity (left-to-right or right-to-left)
result = 100 / 10 / 2; // 5 (left-to-right: (100/10)/2)
cout << "100 / 10 / 2 = " << result << endl;
int a, b, c;
a = b = c = 5; // 5 (right-to-left: a = (b = (c = 5)))
cout << "a = b = c = 5: " << a << ", " << b << ", " << c << endl;
// Complex expression
int x = 5, y = 10, z = 15;
result = x + y * z / 5 - 3;
// Evaluation: y*z=150, 150/5=30, x+30=35, 35-3=32
cout << "5 + 10 * 15 / 5 - 3 = " << result << endl;
// Best practice: use parentheses for clarity
result = x + ((y * z) / 5) - 3; // Same result, clearer intent
return 0;
}
Precedence Table (Highest to Lowest)
| Precedence | Operator | Description | Associativity |
|---|---|---|---|
| 1 | :: |
Scope resolution | Left-to-right |
| 2 | () [] . -> ++ -- |
Postfix | Left-to-right |
| 3 | ++ -- ! ~ + - * & sizeof |
Unary/Prefix | Right-to-left |
| 4 | * / % |
Multiplicative | Left-to-right |
| 5 | + - |
Additive | Left-to-right |
| 6 | << >> |
Shift | Left-to-right |
| 7 | < <= > >= |
Relational | Left-to-right |
| 8 | == != |
Equality | Left-to-right |
| 9 | & |
Bitwise AND | Left-to-right |
| 10 | ^ |
Bitwise XOR | Left-to-right |
| 11 | | |
Bitwise OR | Left-to-right |
| 12 | && |
Logical AND | Left-to-right |
| 13 | || |
Logical OR | Left-to-right |
| 14 | ?: |
Ternary | Right-to-left |
| 15 | = += -= *= /= %= etc. |
Assignment | Right-to-left |
| 16 | , |
Comma | Left-to-right |
a + b * c is
harder to read than a + (b * c).
Key Takeaways
Arithmetic Operators
+, -, *, /, % for math; watch integer division
Relational Operators
Compare values; return true/false
Logical Operators
&&, ||, ! combine conditions; short-circuit
Bitwise Operators
Manipulate individual bits; powerful for flags
Precedence Matters
* / before + -; use parentheses for clarity
Compound Assignment
+=, -=, *= combine operation with assignment
Knowledge Check
Quick Quiz
Test what you have learned about C++ operators