06 Beginner The Hundred
-1 Is Greater Than 1
being one item ahead of schedule has never looked so bad
#include <iostream>
#include <vector>
int main() {
std::vector<int> queue = {10, 20, 30};
int backlog = -1; // we are one item ahead of schedule
unsigned quota = 1; // at most one item may fall behind
std::cout << std::boolalpha;
std::cout << "backlog <= quota is " << (backlog <= quota) << "\n";
if (backlog < queue.size())
std::cout << "backlog fits in the queue\n";
else
std::cout << "backlog exceeds the queue\n";
}
Run it. What does it print?
Answer
-1 is not <= 1, and a backlog of minus one item does not fit in a three-item queue.
Why¶
Comparing a signed value against an unsigned one does not compare the two values. The
usual arithmetic conversions first pull both operands to one common type, and when the
unsigned side is at least as wide as the signed side — as unsigned int and size_t both
are against int here — that common type is the unsigned one. Converting -1 to it never
clamps or fails: it yields that type's largest value, 4294967295 for unsigned int and
18446744073709551615 for the 64-bit size_t that queue.size() returns. Both lines
then ask whether an astronomical number is small, and both correctly say no — with no
undefined behavior anywhere, so the wrong answer comes back identically on every run.
GCC flags both under -Wall (-Wextra alone flags them too): warning: comparison of
integer expressions of different signedness: 'int' and 'unsigned int' [-Wsign-compare].
The fix¶
Compare like with like — cast explicitly, or let C++20 do the work:
std::cout << (backlog <= static_cast<int>(quota)); // explicit, works everywhere
if (backlog < static_cast<int>(queue.size())) // ditto for containers
if (backlog < std::ssize(queue)) // C++20 <iterator>: signed size
if (std::cmp_less(backlog, queue.size())) // C++20 <utility>: compares real values
Takeaway: compare a signed value against an unsigned one at least as wide and both sides turn unsigned — the one place where negative numbers are the biggest of all.
Try it: g++ -std=c++17 main.cpp -o demo && ./demo