Skip to content

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
backlog <= quota is false
backlog exceeds the queue

-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

Open in Compiler Explorer ↗ Quiz this entry