Docs

README

Operators in C++

Table of Contents

  1. Introduction
  2. Arithmetic Operators
  3. Relational Operators
  4. Logical Operators
  5. Bitwise Operators
  6. Assignment Operators
  7. Increment and Decrement Operators
  8. Ternary Operator
  9. Comma Operator
  10. sizeof Operator
  11. Operator Precedence
  12. Type Casting Operators
  13. Common Mistakes
  14. Best Practices
  15. Summary

Introduction

Operators are special symbols that perform operations on operands (variables and values). C++ provides a rich set of operators that can be categorized based on their functionality.

Types of Operators in C++

CategoryOperatorsDescription
Arithmetic+, -, *, /, %Mathematical operations
Relational==, !=, <, >, <=, >=Comparison operations
Logical&&, ||, !Boolean logic
Bitwise&, |, ^, ~, <<, >>Bit manipulation
Assignment=, +=, -=, *=, /=, etc.Value assignment
Increment/Decrement++, --Increase/decrease by 1
Ternary? :Conditional expression
Otherssizeof, ,, ::, ->, .Special operations

Arithmetic Operators

Arithmetic operators perform mathematical calculations on numeric operands.

Basic Arithmetic Operators

OperatorNameExampleResult
+Addition5 + 38
-Subtraction5 - 32
*Multiplication5 * 315
/Division5 / 31 (integer)
%Modulus5 % 32

Integer Division vs Float Division

#include <iostream>
using namespace std;

int main() {
    // Integer division - truncates decimal
    int a = 7, b = 3;
    cout << "7 / 3 = " << a / b << endl;        // Output: 2

    // Float division - preserves decimal
    double x = 7.0, y = 3.0;
    cout << "7.0 / 3.0 = " << x / y << endl;    // Output: 2.33333

    // Mixed division
    cout << "7 / 3.0 = " << a / y << endl;      // Output: 2.33333 (int promoted to double)

    return 0;
}

Modulus Operator

The modulus operator % returns the remainder of integer division:

int remainder = 17 % 5;   // remainder = 2 (17 = 5*3 + 2)
int even_check = 10 % 2;  // even_check = 0 (10 is even)
int odd_check = 11 % 2;   // odd_check = 1 (11 is odd)

Note: Modulus only works with integers. For floating-point, use fmod() from <cmath>.

Unary Plus and Minus

int a = 5;
int b = -a;    // b = -5 (unary minus)
int c = +a;    // c = 5 (unary plus, rarely used)
int d = -(-a); // d = 5 (double negative)

Relational Operators

Relational operators compare two values and return a boolean result (true or false).

Comparison Operators

OperatorMeaningExampleResult
==Equal to5 == 5true
!=Not equal to5 != 3true
<Less than3 < 5true
>Greater than5 > 3true
<=Less than or equal5 <= 5true
>=Greater than or equal5 >= 3true

Usage Examples

#include <iostream>
using namespace std;

int main() {
    int x = 10, y = 20;

    cout << boolalpha;  // Print "true"/"false" instead of 1/0

    cout << "x == y: " << (x == y) << endl;  // false
    cout << "x != y: " << (x != y) << endl;  // true
    cout << "x < y: " << (x < y) << endl;    // true
    cout << "x > y: " << (x > y) << endl;    // false
    cout << "x <= y: " << (x <= y) << endl;  // true
    cout << "x >= y: " << (x >= y) << endl;  // false

    return 0;
}

Comparing Floating-Point Numbers

Warning: Direct comparison of floating-point numbers can be unreliable due to precision issues.

#include <cmath>

double a = 0.1 + 0.2;
double b = 0.3;

// BAD: Direct comparison
if (a == b) { /* may not work! */ }

// GOOD: Use epsilon comparison
const double EPSILON = 1e-9;
if (fabs(a - b) < EPSILON) {
    cout << "Numbers are approximately equal" << endl;
}

Three-Way Comparison (C++20)

C++20 introduces the spaceship operator <=>:

#include <compare>

int a = 5, b = 10;
auto result = a <=> b;

if (result < 0)  cout << "a is less than b";
if (result == 0) cout << "a equals b";
if (result > 0)  cout << "a is greater than b";

Logical Operators

Logical operators combine boolean expressions.

Truth Tables

AND Operator (&&)

ABA && B
falsefalsefalse
falsetruefalse
truefalsefalse
truetruetrue

OR Operator (||)

ABA || B
falsefalsefalse
falsetruetrue
truefalsetrue
truetruetrue

NOT Operator (!)

A!A
falsetrue
truefalse

Short-Circuit Evaluation

C++ uses short-circuit evaluation for logical operators:

int x = 0;

// AND: If first operand is false, second is not evaluated
if (x != 0 && 10 / x > 1) {
    // Safe: 10/x won't execute when x is 0
}

// OR: If first operand is true, second is not evaluated
if (x == 0 || 10 / x > 1) {
    // Safe: 10/x won't execute when x is 0
}

Practical Examples

int age = 25;
bool hasLicense = true;
bool hasInsurance = true;

// Multiple conditions
if (age >= 18 && hasLicense && hasInsurance) {
    cout << "Can drive legally" << endl;
}

// Either condition
if (age < 13 || age >= 65) {
    cout << "Eligible for discount" << endl;
}

// Negation
if (!hasLicense) {
    cout << "Cannot drive" << endl;
}

Bitwise Operators

Bitwise operators work on individual bits of integer values.

Bitwise Operators Overview

OperatorNameDescription
&ANDSets bit to 1 if both bits are 1
|ORSets bit to 1 if at least one bit is 1
^XORSets bit to 1 if bits are different
~NOTInverts all bits
<<Left shiftShifts bits left, fills with 0
>>Right shiftShifts bits right

Bitwise AND (&)

    5 = 0101
    3 = 0011
    --------
5 & 3 = 0001 = 1
int result = 5 & 3;  // result = 1

Bitwise OR (|)

    5 = 0101
    3 = 0011
    --------
5 | 3 = 0111 = 7
int result = 5 | 3;  // result = 7

Bitwise XOR (^)

    5 = 0101
    3 = 0011
    --------
5 ^ 3 = 0110 = 6
int result = 5 ^ 3;  // result = 6

// XOR swap trick (without temp variable)
int a = 5, b = 3;
a = a ^ b;  // a = 6
b = a ^ b;  // b = 5
a = a ^ b;  // a = 3

Bitwise NOT (~)

int a = 5;      // Binary: 00000101
int b = ~a;     // Binary: 11111010 = -6 (two's complement)

Left Shift (<<)

int a = 5;           // Binary: 00000101
int b = a << 1;      // Binary: 00001010 = 10
int c = a << 2;      // Binary: 00010100 = 20

// Left shift by n is equivalent to multiplying by 2^n
// a << n == a * 2^n

Right Shift (>>)

int a = 20;          // Binary: 00010100
int b = a >> 1;      // Binary: 00001010 = 10
int c = a >> 2;      // Binary: 00000101 = 5

// Right shift by n is equivalent to dividing by 2^n
// a >> n == a / 2^n

Practical Applications

// Check if number is odd or even
bool isOdd = (n & 1);  // Last bit is 1 for odd numbers

// Set a bit at position pos
int setBit = n | (1 << pos);

// Clear a bit at position pos
int clearBit = n & ~(1 << pos);

// Toggle a bit at position pos
int toggleBit = n ^ (1 << pos);

// Check if bit at position pos is set
bool isBitSet = (n & (1 << pos)) != 0;

Assignment Operators

Assignment operators assign values to variables.

Simple Assignment

int x = 10;       // Assign 10 to x
int y = x;        // Assign value of x to y
int a, b, c;
a = b = c = 5;    // Chained assignment (right to left)

Compound Assignment Operators

OperatorExampleEquivalent
+=x += 5x = x + 5
-=x -= 5x = x - 5
*=x *= 5x = x * 5
/=x /= 5x = x / 5
%=x %= 5x = x % 5
&=x &= 5x = x & 5
|=x |= 5x = x | 5
^=x ^= 5x = x ^ 5
<<=x <<= 2x = x << 2
>>=x >>= 2x = x >> 2
int x = 10;

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

Increment and Decrement Operators

Pre-increment vs Post-increment

OperatorNameDescription
++xPre-incrementIncrement first, then use value
x++Post-incrementUse value first, then increment
--xPre-decrementDecrement first, then use value
x--Post-decrementUse value first, then decrement
#include <iostream>
using namespace std;

int main() {
    int a = 5, b = 5;

    cout << "Pre-increment: " << ++a << endl;   // Output: 6, a is now 6
    cout << "Post-increment: " << b++ << endl;  // Output: 5, b is now 6

    int x = 10, y = 10;

    cout << "Pre-decrement: " << --x << endl;   // Output: 9, x is now 9
    cout << "Post-decrement: " << y-- << endl;  // Output: 10, y is now 9

    return 0;
}

In Expressions

int a = 5;
int b = ++a + 10;   // a becomes 6, then b = 6 + 10 = 16

int x = 5;
int y = x++ + 10;   // y = 5 + 10 = 15, then x becomes 6

In Loops

// Both achieve the same result in simple loops
for (int i = 0; i < 10; ++i) { }  // Pre-increment (slightly more efficient for iterators)
for (int i = 0; i < 10; i++) { }  // Post-increment

Ternary Operator

The ternary operator (?:) is a shorthand for simple if-else statements.

Syntax

condition ? expression_if_true : expression_if_false

Examples

int a = 10, b = 20;

// Simple ternary
int max = (a > b) ? a : b;  // max = 20

// In output
cout << "Result: " << ((a > b) ? "a is greater" : "b is greater") << endl;

// Nested ternary (use sparingly!)
int x = 5;
string result = (x > 0) ? "positive" : (x < 0) ? "negative" : "zero";

// Equivalent if-else
int max2;
if (a > b) {
    max2 = a;
} else {
    max2 = b;
}

When to Use

Good use cases:

  • Simple value selection
  • Inline assignments
  • Return statements

Avoid when:

  • Logic is complex
  • Multiple statements needed
  • Nested ternaries become confusing

Comma Operator

The comma operator evaluates multiple expressions and returns the last one.

int a, b, c;

// Multiple declarations
int x = 1, y = 2, z = 3;

// In expressions (returns last value)
int result = (a = 5, b = 10, a + b);  // result = 15

// In for loops
for (int i = 0, j = 10; i < j; ++i, --j) {
    cout << i << " " << j << endl;
}

sizeof Operator

The sizeof operator returns the size in bytes of a type or variable.

#include <iostream>
using namespace std;

int main() {
    // Size of types
    cout << "char: " << sizeof(char) << " bytes" << endl;        // 1
    cout << "int: " << sizeof(int) << " bytes" << endl;          // 4 (typically)
    cout << "double: " << sizeof(double) << " bytes" << endl;    // 8
    cout << "long long: " << sizeof(long long) << " bytes" << endl;  // 8

    // Size of variables
    int arr[10];
    cout << "Array of 10 ints: " << sizeof(arr) << " bytes" << endl;  // 40
    cout << "Number of elements: " << sizeof(arr)/sizeof(arr[0]) << endl;  // 10

    // Size of expressions
    cout << "sizeof(5 + 3.14): " << sizeof(5 + 3.14) << " bytes" << endl;  // 8 (double)

    return 0;
}

Operator Precedence

Operators are evaluated based on their precedence (priority) and associativity.

Precedence Table (Highest to Lowest)

PriorityOperatorsAssociativity
1::Left to right
2() [] -> . ++ -- (postfix)Left to right
3++ -- (prefix) + - (unary) ! ~ * & sizeofRight to left
4* / %Left to right
5+ -Left to right
6<< >>Left to right
7< <= > >=Left to right
8== !=Left to right
9&Left to right
10^Left to right
11|Left to right
12&&Left to right
13||Left to right
14?:Right to left
15= += -= *= /= etc.Right to left
16,Left to right

Examples

int result;

// Precedence affects evaluation order
result = 2 + 3 * 4;        // 14 (not 20), * before +
result = (2 + 3) * 4;      // 20, parentheses override

// Multiple operators
result = 10 - 5 - 2;       // 3, left to right
result = 2 * 3 + 4 / 2;    // 6 + 2 = 8

// Assignment is right-to-left
int a, b, c;
a = b = c = 10;            // c=10, b=c, a=b

// Logical operators
bool x = true || false && false;  // true (&& before ||)
bool y = (true || false) && false; // false

Best Practice: Use parentheses to make precedence explicit and code more readable.


Type Casting Operators

C-Style Casting

int a = 10;
double b = (double)a;       // C-style cast
double c = double(a);       // Function-style cast

C++ Casting Operators

static_cast

For well-defined type conversions:

double d = 3.14;
int i = static_cast<int>(d);  // i = 3

// Pointer conversion in class hierarchy
Derived* dp = new Derived();
Base* bp = static_cast<Base*>(dp);

dynamic_cast

For safe downcasting with polymorphism:

Base* bp = new Derived();
Derived* dp = dynamic_cast<Derived*>(bp);
if (dp != nullptr) {
    // Safe to use dp
}

const_cast

For adding/removing const qualifier:

const int* cp = &a;
int* p = const_cast<int*>(cp);  // Remove const (use carefully!)

reinterpret_cast

For low-level bit reinterpretation:

int* ip = new int(65);
char* cp = reinterpret_cast<char*>(ip);  // Dangerous!

Common Mistakes

1. Assignment vs Comparison

// WRONG: Assignment in condition
if (x = 5) { }  // Always true, assigns 5 to x

// CORRECT: Comparison
if (x == 5) { }  // Compares x with 5

2. Integer Division

// WRONG: Expects decimal result
double result = 5 / 2;  // result = 2.0

// CORRECT: Use float operand
double result = 5.0 / 2;  // result = 2.5

3. Operator Precedence

// WRONG: Unexpected result
if (a & b == 0) { }  // Parsed as: a & (b == 0)

// CORRECT: Use parentheses
if ((a & b) == 0) { }

4. Increment in Complex Expressions

// UNDEFINED BEHAVIOR
int i = 1;
int j = i++ + ++i;  // Result is undefined!

// CORRECT: Separate statements
int i = 1;
int temp = i++;
int j = temp + ++i;

5. Floating-Point Comparison

// WRONG: Direct comparison
if (0.1 + 0.2 == 0.3) { }  // May be false!

// CORRECT: Use epsilon
if (fabs((0.1 + 0.2) - 0.3) < 1e-9) { }

Best Practices

  1. Use parentheses for clarity

    result = (a * b) + (c / d);  // Clear precedence
    
  2. Prefer prefix increment for non-primitive types

    for (auto it = vec.begin(); it != vec.end(); ++it)  // More efficient
    
  3. Avoid complex expressions

    // Bad
    x = a++ + ++b * c-- / ++d;
    
    // Good: Break into multiple statements
    ++b;
    x = a + b * c / d;
    --c;
    ++d;
    ++a;
    
  4. Use compound assignment when possible

    x += 5;  // Cleaner than x = x + 5
    
  5. Be careful with signed/unsigned operations

    unsigned int u = 10;
    int s = -5;
    // u + s may give unexpected results due to implicit conversion
    

Summary

CategoryKey Points
Arithmetic+, -, *, /, %; Integer division truncates
RelationalReturn bool; Use epsilon for float comparison
LogicalShort-circuit evaluation; &&, ||, !
BitwiseWork on bits; Useful for flags and optimization
Assignment= and compound operators (+=, -=, etc.)
Increment/DecrementPre vs Post affects when value changes
Ternary?: for simple conditionals
PrecedenceUse parentheses when in doubt
CastingPrefer C++ casts over C-style casts

Compilation

g++ -std=c++17 -Wall -Wextra examples.cpp -o examples
./examples

Navigation


Master operators to write efficient and correct C++ expressions!

README - C++ Tutorial | DeepML