Module 2.1

Operators in C++

Master the building blocks of expressions in C++. Learn arithmetic, relational, logical, bitwise, and assignment operators. Understand operator precedence and associativity to write clear and efficient code.

45 min read
Beginner
Hands-on Examples
What You'll Learn
  • Arithmetic operators
  • Relational & logical operators
  • Bitwise operators
  • Assignment operators
  • Operator precedence
Contents
01

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.

Concept

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

02

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;
}
Integer Division Warning: When dividing two integers, C++ performs integer division and truncates the decimal part. Use floating-point numbers or cast to get decimal results: (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!
03

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
04

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 (&&)
ABA && B
TTT
TFF
FTF
FFF
OR (||)
ABA || B
TTT
TFT
FTT
FFF
NOT (!)
A!A
TF
FT
05

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
06

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 = ba = b
+=a += ba = a + b
-=a -= ba = a - b
*=a *= ba = a * b
/=a /= ba = a / b
%=a %= ba = a % b
&=a &= ba = a & b
|=a |= ba = a | b
^=a ^= ba = a ^ b
<<=a <<= ba = a << b
>>=a >>= ba = a >> b
07

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;
}
08

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
Best Practice: When in doubt, use parentheses! They make your code clearer and prevent precedence-related bugs. 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

1 What is the result of 17 / 5 in C++ (integer division)?
2 What does the expression (a && b) return when a is true and b is false?
3 What is 5 << 2 (left shift)?
4 What is the value of x after: int x = 5; x += 3;?
5 What is the result of: 2 + 3 * 4?
6 Which operator is used for the ternary conditional expression?
Answer all questions to check your score