Relational & Logical Operators
bool
(true/false). Logical operators combine or invert
boolean expressions. Together they form the backbone of every conditional and
loop in C++.
Relational Operators
Operator | Meaning | Example |
|---|---|---|
== | Equal to | a == b |
!= | Not equal to | a != b |
Greater than | a > b | |
< | Less than | a < b |
= | Greater than or equal to | a >= b |
<= | Less than or equal to | a <= b |
Logical Operators
Operator | Meaning | Example |
|---|---|---|
&& | Logical AND — true only if both sides are true | isValid && isReady |
|| | Logical OR — true if at least one side is true | isAdmin || isOwner |
! | Logical NOT — inverts a boolean | !isExpired |
Short-Circuit Evaluation
&& and || do not always evaluate their
right-hand side. If the left side of && is false,
the overall result must be false regardless of the right side, so
the right side is skipped entirely. The same applies to || when
the left side is true. This is not just an optimization — code
routinely relies on it for safety.
#include <iostream>
bool isSafeToDivide(int numerator, int denominator) {
// If denominator == 0, the left side is false, so the division on the
// right is NEVER evaluated — this pattern safely guards against
// division by zero.
return denominator != 0 && (numerator / denominator) > 1;
}
int main() {
std::cout << isSafeToDivide(10, 0) << std::endl; // false, no crash
return 0;
}Never Compare Floating-Point Numbers with ==
float, double) cannot exactly represent most decimal fractions in binary. Two computations that are mathematically equal can end up with tiny representation differences, so == often returns false when you expect true. Instead, compare whether the values are within a small tolerance (epsilon) of each other.#include <cmath>
#include <iostream>
int main() {
double a = 0.1 + 0.2;
double b = 0.3;
std::cout << (a == b) << std::endl; // false! (0.30000000000000004 != 0.3)
// Correct approach: compare within a small epsilon
const double epsilon = 1e-9;
bool almostEqual = std::fabs(a - b) < epsilon;
std::cout << almostEqual << std::endl; // true
return 0;
}Comparing Different Numeric Types
Comparing a signed and an unsigned integer can silently produce the wrong answer because the compiler converts the signed value to unsigned before comparing — a negative number becomes a very large positive one. This is covered in depth on the Type Modifiers page; the short version:
int signedValue = -1; unsigned int unsignedValue = 1; // signedValue is converted to unsigned, becoming a huge number: std::cout << (signedValue < unsignedValue) << std::endl; // false — surprising!
-Wsign-compare in GCC/Clang). Treat that warning seriously rather than suppressing it.Use
==/!=freely for integers, characters, booleans, and pointersNever use
==/!=directly onfloat/double— use an epsilon comparisonMatch signedness before comparing mixed integer types, or cast explicitly