README
Operators in C++
Table of Contents
- •Introduction
- •Arithmetic Operators
- •Relational Operators
- •Logical Operators
- •Bitwise Operators
- •Assignment Operators
- •Increment and Decrement Operators
- •Ternary Operator
- •Comma Operator
- •sizeof Operator
- •Operator Precedence
- •Type Casting Operators
- •Common Mistakes
- •Best Practices
- •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++
| Category | Operators | Description |
|---|---|---|
| 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 |
| Others | sizeof, ,, ::, ->, . | Special operations |
Arithmetic Operators
Arithmetic operators perform mathematical calculations on numeric operands.
Basic Arithmetic Operators
| Operator | Name | Example | Result |
|---|---|---|---|
+ | Addition | 5 + 3 | 8 |
- | Subtraction | 5 - 3 | 2 |
* | Multiplication | 5 * 3 | 15 |
/ | Division | 5 / 3 | 1 (integer) |
% | Modulus | 5 % 3 | 2 |
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
| Operator | Meaning | Example | Result |
|---|---|---|---|
== | Equal to | 5 == 5 | true |
!= | Not equal to | 5 != 3 | true |
< | Less than | 3 < 5 | true |
> | Greater than | 5 > 3 | true |
<= | Less than or equal | 5 <= 5 | true |
>= | Greater than or equal | 5 >= 3 | true |
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 (&&)
| A | B | A && B |
|---|---|---|
| false | false | false |
| false | true | false |
| true | false | false |
| true | true | true |
OR Operator (||)
| A | B | A || B |
|---|---|---|
| false | false | false |
| false | true | true |
| true | false | true |
| true | true | true |
NOT Operator (!)
| A | !A |
|---|---|
| false | true |
| true | false |
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
| Operator | Name | Description |
|---|---|---|
& | AND | Sets bit to 1 if both bits are 1 |
| | OR | Sets bit to 1 if at least one bit is 1 |
^ | XOR | Sets bit to 1 if bits are different |
~ | NOT | Inverts all bits |
<< | Left shift | Shifts bits left, fills with 0 |
>> | Right shift | Shifts 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
| Operator | Example | Equivalent |
|---|---|---|
+= | x += 5 | x = x + 5 |
-= | x -= 5 | x = x - 5 |
*= | x *= 5 | x = x * 5 |
/= | x /= 5 | x = x / 5 |
%= | x %= 5 | x = x % 5 |
&= | x &= 5 | x = x & 5 |
|= | x |= 5 | x = x | 5 |
^= | x ^= 5 | x = x ^ 5 |
<<= | x <<= 2 | x = x << 2 |
>>= | x >>= 2 | x = 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
| Operator | Name | Description |
|---|---|---|
++x | Pre-increment | Increment first, then use value |
x++ | Post-increment | Use value first, then increment |
--x | Pre-decrement | Decrement first, then use value |
x-- | Post-decrement | Use 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)
| Priority | Operators | Associativity |
|---|---|---|
| 1 | :: | Left to right |
| 2 | () [] -> . ++ -- (postfix) | Left to right |
| 3 | ++ -- (prefix) + - (unary) ! ~ * & sizeof | Right 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
- •
Use parentheses for clarity
result = (a * b) + (c / d); // Clear precedence - •
Prefer prefix increment for non-primitive types
for (auto it = vec.begin(); it != vec.end(); ++it) // More efficient - •
Avoid complex expressions
// Bad x = a++ + ++b * c-- / ++d; // Good: Break into multiple statements ++b; x = a + b * c / d; --c; ++d; ++a; - •
Use compound assignment when possible
x += 5; // Cleaner than x = x + 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
| Category | Key Points |
|---|---|
| Arithmetic | +, -, *, /, %; Integer division truncates |
| Relational | Return bool; Use epsilon for float comparison |
| Logical | Short-circuit evaluation; &&, ||, ! |
| Bitwise | Work on bits; Useful for flags and optimization |
| Assignment | = and compound operators (+=, -=, etc.) |
| Increment/Decrement | Pre vs Post affects when value changes |
| Ternary | ?: for simple conditionals |
| Precedence | Use parentheses when in doubt |
| Casting | Prefer C++ casts over C-style casts |
Compilation
g++ -std=c++17 -Wall -Wextra examples.cpp -o examples
./examples
Navigation
| Previous | Up | Next |
|---|---|---|
| Variables and Data Types | Foundations | Control Flow |
Master operators to write efficient and correct C++ expressions!