C++ Operators Complete Guide
Precedence Rules

C++ Operators: Complete Guide with Examples

Master all C++ operators: arithmetic, relational, logical, bitwise, assignment, and special operators. Learn operator precedence, usage examples, and best practices.

Arithmetic

Math Operations

Relational

Comparison

Logical

Boolean Logic

Bitwise

Bit Operations

Introduction to C++ Operators

Operators are special symbols that perform operations on variables and values. C++ provides a rich set of operators that can be classified into several categories based on their functionality.

Operator Characteristics
  • Arity: Number of operands (unary, binary, ternary)
  • Precedence: Order of evaluation
  • Associativity: Direction of evaluation (left-to-right or right-to-left)
  • Overloadable: Can be redefined for user-defined types
Key Concepts
  • Operand: Value/variable on which operator acts
  • Expression: Combination of operators and operands
  • Lvalue vs Rvalue: Location vs value distinction
  • Side Effects: Changes to operands during evaluation

Basic Operator Example

Operators work with operands to form expressions: result = operand1 operator operand2

Basic Operator Usage
#include <iostream>
using namespace std;

int main() {
    // Arithmetic operators
    int a = 10, b = 3;
    int sum = a + b;      // 13
    int diff = a - b;     // 7
    int product = a * b;  // 30
    int quotient = a / b; // 3 (integer division)
    int remainder = a % b; // 1
    
    // Relational operators
    bool isEqual = (a == b);      // false
    bool isGreater = (a > b);     // true
    bool isNotEqual = (a != b);   // true
    
    // Logical operators
    bool condition1 = true, condition2 = false;
    bool andResult = condition1 && condition2; // false
    bool orResult = condition1 || condition2;  // true
    bool notResult = !condition1;              // false
    
    cout << "Sum: " << sum << endl;
    cout << "a == b: " << boolalpha << isEqual << endl;
    cout << "condition1 && condition2: " << andResult << endl;
    
    return 0;
}

Complete C++ Operators Reference

The following table provides a comprehensive reference of all C++ operators with examples and descriptions:

Category Operator Name Description & Example
Arithmetic Operators
Arithmetic + Addition Adds two operands: a + b
Arithmetic - Subtraction Subtracts second operand: a - b
Arithmetic * Multiplication Multiplies two operands: a * b
Arithmetic / Division Divides numerator by denominator: a / b
Arithmetic % Modulus Remainder after division: a % b
Arithmetic ++ Increment Increases value by 1: a++ (post), ++a (pre)
Arithmetic -- Decrement Decreases value by 1: a-- (post), --a (pre)
Relational/Comparison Operators
Relational == Equal to Checks equality: a == b returns true if equal
Relational != Not equal to Checks inequality: a != b returns true if not equal
Relational > Greater than a > b returns true if a is greater
Relational < Less than a < b returns true if a is less
Relational >= Greater than or equal a >= b returns true if a is greater or equal
Relational <= Less than or equal a <= b returns true if a is less or equal
Logical Operators
Logical && Logical AND a && b returns true if both are true
Logical || Logical OR a || b returns true if either is true
Logical ! Logical NOT !a returns true if a is false
Bitwise Operators
Bitwise & Bitwise AND Sets each bit to 1 if both bits are 1: a & b
Bitwise | Bitwise OR Sets each bit to 1 if either bit is 1: a | b
Bitwise ^ Bitwise XOR Sets each bit to 1 if only one bit is 1: a ^ b
Bitwise ~ Bitwise NOT Inverts all bits: ~a
Bitwise << Left shift Shifts bits left, fills with 0: a << n
Bitwise >> Right shift Shifts bits right: a >> n
Assignment Operators
Assignment = Simple assignment Assigns right operand to left: a = b
Assignment += Add AND assign a += b is same as a = a + b
Assignment -= Subtract AND assign a -= b is same as a = a - b
Assignment *= Multiply AND assign a *= b is same as a = a * b
Assignment /= Divide AND assign a /= b is same as a = a / b
Assignment %= Modulus AND assign a %= b is same as a = a % b
Assignment &= Bitwise AND assign a &= b is same as a = a & b
Assignment |= Bitwise OR assign a |= b is same as a = a | b
Assignment ^= Bitwise XOR assign a ^= b is same as a = a ^ b
Assignment <<= Left shift AND assign a <<= n is same as a = a << n
Assignment >>= Right shift AND assign a >>= n is same as a = a >> n
Special Operators
Special ?: Ternary/Conditional condition ? expr1 : expr2 - If condition true, expr1 else expr2
Special , Comma expr1, expr2 - Evaluates both, returns expr2
Special sizeof Size of sizeof(type) - Returns size in bytes
Special typeid Type identification typeid(expr) - Returns type information
Special static_cast Static cast static_cast<type>(expr) - Compile-time type conversion
Special dynamic_cast Dynamic cast dynamic_cast<type>(expr) - Runtime type conversion (polymorphic)
Special const_cast Const cast const_cast<type>(expr) - Adds/removes const qualifier
Special reinterpret_cast Reinterpret cast reinterpret_cast<type>(expr) - Reinterprets bit pattern
Special . and -> Member access obj.member (direct), ptr->member (via pointer)
Special :: Scope resolution Class::member or namespace::member
Special new Dynamic memory allocation new type - Allocates memory on heap
Special delete Dynamic memory deallocation delete ptr - Frees heap memory
Special () Function call function(arg1, arg2) - Calls a function
Special [] Array subscript array[index] - Accesses array element

Operator Examples with Code

Arithmetic Operators

Arithmetic Operations
#include <iostream>
using namespace std;

int main() {
    int a = 15, b = 4;
    
    cout << "a = " << a << ", b = " << b << endl;
    cout << "a + b = " << a + b << endl;      // 19
    cout << "a - b = " << a - b << endl;      // 11
    cout << "a * b = " << a * b << endl;      // 60
    cout << "a / b = " << a / b << endl;      // 3 (integer division)
    cout << "a % b = " << a % b << endl;      // 3
    
    // Floating point division
    double x = 15.0, y = 4.0;
    cout << "x / y = " << x / y << endl;      // 3.75
    
    // Increment/Decrement
    int count = 5;
    cout << "count = " << count << endl;
    cout << "count++ = " << count++ << endl;  // Prints 5, then becomes 6
    cout << "++count = " << ++count << endl;  // Becomes 7, then prints 7
    cout << "count-- = " << count-- << endl;  // Prints 7, then becomes 6
    cout << "--count = " << --count << endl;  // Becomes 5, then prints 5
    
    return 0;
}

Relational and Logical Operators

Comparison and Logic
#include <iostream>
using namespace std;

int main() {
    int age = 25;
    double salary = 50000;
    bool hasLicense = true;
    
    // Relational operators
    cout << boolalpha; // Print true/false instead of 1/0
    cout << "age >= 18: " << (age >= 18) << endl;          // true
    cout << "salary < 60000: " << (salary < 60000) << endl; // true
    cout << "age == 25: " << (age == 25) << endl;           // true
    cout << "age != 30: " << (age != 30) << endl;           // true
    
    // Logical operators
    bool canDrive = (age >= 18) && hasLicense;
    bool isEligible = (age > 21) || (salary > 40000);
    bool isInvalid = !(age > 0);
    
    cout << "Can drive: " << canDrive << endl;      // true
    cout << "Is eligible: " << isEligible << endl;  // true
    cout << "Is invalid age: " << isInvalid << endl; // false
    
    // Short-circuit evaluation
    int x = 5, y = 0;
    bool result = (y != 0) && (x / y > 2); // Safe due to short-circuit
    cout << "Short-circuit result: " << result << endl;
    
    return 0;
}

Bitwise Operators

Bit Manipulation
#include <iostream>
#include <bitset> // For binary display
using namespace std;

int main() {
    unsigned char a = 0b00110101; // 53 in decimal
    unsigned char b = 0b00001111; // 15 in decimal
    
    cout << "a = " << bitset<8>(a) << " (" << (int)a << ")" << endl;
    cout << "b = " << bitset<8>(b) << " (" << (int)b << ")" << endl;
    
    // Bitwise operations
    cout << "a & b = " << bitset<8>(a & b) << " (" << (int)(a & b) << ")" << endl;
    cout << "a | b = " << bitset<8>(a | b) << " (" << (int)(a | b) << ")" << endl;
    cout << "a ^ b = " << bitset<8>(a ^ b) << " (" << (int)(a ^ b) << ")" << endl;
    cout << "~a = " << bitset<8>(~a) << " (" << (int)(~a) << ")" << endl;
    
    // Shift operations
    cout << "a << 2 = " << bitset<8>(a << 2) << " (" << (int)(a << 2) << ")" << endl;
    cout << "a >> 2 = " << bitset<8>(a >> 2) << " (" << (int)(a >> 2) << ")" << endl;
    
    // Common bitwise uses
    int flags = 0;
    const int FLAG_A = 1 << 0; // 0001
    const int FLAG_B = 1 << 1; // 0010
    const int FLAG_C = 1 << 2; // 0100
    const int FLAG_D = 1 << 3; // 1000
    
    // Set flags
    flags |= FLAG_A; // Set flag A
    flags |= FLAG_C; // Set flag C
    
    // Check flag
    if (flags & FLAG_A) {
        cout << "Flag A is set" << endl;
    }
    
    // Clear flag
    flags &= ~FLAG_C; // Clear flag C
    
    // Toggle flag
    flags ^= FLAG_B; // Toggle flag B
    
    return 0;
}

Operator Precedence and Associativity

Operator precedence determines the order of evaluation in expressions. When operators have the same precedence, associativity determines the direction of evaluation.

Important Rule

Use parentheses () to explicitly specify evaluation order when in doubt. This improves readability and prevents bugs.

Precedence Category Operators Associativity
1 (Highest) Scope resolution :: Left to right
2 Postfix () [] -> . ++ -- Left to right
3 Unary ++ -- + - ! ~ (type) * & sizeof Right to left
4 Member access .* ->* Left to right
5 Multiplicative * / % Left to right
6 Additive + - Left to right
7 Bitwise shift << >> Left to right
8 Relational < <= > >= Left to right
9 Equality == != Left to right
10 Bitwise AND & Left to right
11 Bitwise XOR ^ Left to right
12 Bitwise OR | Left to right
13 Logical AND && Left to right
14 Logical OR || Left to right
15 Conditional ?: Right to left
16 Assignment = += -= *= /= %= &= ^= |= <<= >>= Right to left
17 (Lowest) Comma , Left to right
Precedence Examples
#include <iostream>
using namespace std;

int main() {
    int a = 5, b = 10, c = 15;
    
    // Without parentheses (rely on precedence)
    int result1 = a + b * c;      // 5 + (10 * 15) = 155
    int result2 = a * b + c;      // (5 * 10) + 15 = 65
    int result3 = a > b && b < c; // (5 > 10) && (10 < 15) = false
    
    // With parentheses (explicit order)
    int result4 = (a + b) * c;    // (5 + 10) * 15 = 225
    int result5 = a * (b + c);    // 5 * (10 + 15) = 125
    bool result6 = (a > b) && (b < c); // false
    
    cout << "a + b * c = " << result1 << endl;
    cout << "a * b + c = " << result2 << endl;
    cout << "a > b && b < c = " << boolalpha << result3 << endl;
    cout << "(a + b) * c = " << result4 << endl;
    cout << "a * (b + c) = " << result5 << endl;
    
    // Common precedence pitfalls
    int x = 5;
    int y = x++ + ++x; // Undefined behavior! Avoid multiple increments in same expression
    cout << "y (undefined behavior): " << y << endl;
    
    return 0;
}
Undefined Behavior Warning: Avoid modifying the same variable multiple times in the same expression (e.g., x++ + ++x). The result is undefined and varies between compilers.

Special Operators in Detail

Ternary Operator

condition ? expr1 : expr2 - Compact if-else replacement.

int max = (a > b) ? a : b;
string result = (score >= 50) 
                ? "Pass" : "Fail";
sizeof Operator

Returns size in bytes of type or variable.

sizeof(int);      // 4 (usually)
sizeof(double);   // 8 (usually)
int arr[10];
sizeof(arr);      // 40 (if int is 4 bytes)
Type Cast Operators

C++ offers four casting operators for type conversion.

// Static cast (compile-time)
double d = 3.14;
int i = static_cast(d);

// Dynamic cast (runtime, polymorphic)
Base* b = new Derived();
Derived* d = dynamic_cast(b);
new and delete

Dynamic memory allocation and deallocation.

// Single object
int* ptr = new int(42);
delete ptr;

// Array
int* arr = new int[10];
delete[] arr;
Special Operators Example
#include <iostream>
#include <typeinfo>
using namespace std;

int main() {
    // Ternary operator
    int age = 20;
    string status = (age >= 18) ? "Adult" : "Minor";
    cout << "Status: " << status << endl;
    
    // Comma operator
    int a = (cout << "Hello, ", 5);
    cout << "\na = " << a << endl;
    
    // sizeof operator
    cout << "Size of int: " << sizeof(int) << " bytes" << endl;
    cout << "Size of double: " << sizeof(double) << " bytes" << endl;
    
    // typeid operator
    cout << "Type of age: " << typeid(age).name() << endl;
    cout << "Type of status: " << typeid(status).name() << endl;
    
    // Scope resolution
    int value = 100;
    {
        int value = 200; // Shadows outer value
        cout << "Inner value: " << value << endl;
        cout << "Outer value: " << ::value << endl; // Access global/namespace
    }
    
    // Member access operators
    struct Point {
        int x, y;
    };
    
    Point p = {10, 20};
    Point* ptr = &p;
    
    cout << "p.x = " << p.x << endl;      // Direct member access
    cout << "ptr->y = " << ptr->y << endl; // Indirect member access
    
    return 0;
}

Best Practices and Common Pitfalls

Do's
  • Use parentheses for complex expressions
  • Use compound assignment operators for brevity
  • Prefer prefix increment/decrement (++i) when value not needed
  • Use const with pointers to prevent modification
  • Check for division by zero before division/modulus
  • Use bitwise operators only for bit manipulation
  • Initialize variables before using them
Don'ts
  • Don't use assignment (=) instead of equality (==)
  • Don't modify same variable multiple times in one expression
  • Don't use bitwise operators as logical operators
  • Don't forget operator precedence (use parentheses)
  • Don't use C-style casts (use C++ casts instead)
  • Don't use sizeof on pointer types for array size
  • Don't ignore compiler warnings about type conversions
Common Operator Mistakes:
  1. if (x = 5) instead of if (x == 5) (assignment vs comparison)
  2. a < b < c instead of (a < b) && (b < c)
  3. Integer division when expecting floating-point: 5/2 = 2 not 2.5
  4. Using ! (logical NOT) instead of ~ (bitwise NOT)
  5. Forgetting that && and || use short-circuit evaluation
Good Practices Example
#include <iostream>
using namespace std;

int main() {
    // GOOD PRACTICES
    
    // 1. Use parentheses for clarity
    int result = (2 + 3) * 4; // Clear: (2+3)*4 = 20
    
    // 2. Use compound assignment
    int total = 0;
    total += 5;  // Better than: total = total + 5
    total *= 2;  // Better than: total = total * 2
    
    // 3. Check before division
    int numerator = 10, denominator = 0;
    if (denominator != 0) {
        int quotient = numerator / denominator;
    } else {
        cout << "Error: Division by zero!" << endl;
    }
    
    // 4. Use prefix increment when value not needed
    for (int i = 0; i < 10; ++i) { // ++i is slightly faster than i++
        cout << i << " ";
    }
    cout << endl;
    
    // 5. Avoid common mistakes
    int x = 5, y = 10;
    
    // WRONG: if (x = y) // Assigns y to x, always true if y != 0
    // RIGHT:
    if (x == y) {
        cout << "x equals y" << endl;
    }
    
    // WRONG: if (0 < x < 5) // Doesn't work as expected
    // RIGHT:
    if (x > 0 && x < 5) {
        cout << "x is between 0 and 5" << endl;
    }
    
    // 6. Use appropriate casts
    double pi = 3.14159;
    int intPi = static_cast<int>(pi); // Explicit conversion
    cout << "Integer part of pi: " << intPi << endl;
    
    return 0;
}