Compiler warnings

C++ warning: comparison of integer expressions of different signedness

This warning means a comparison mixes a signed integer, such as int, with an unsigned integer type such as vector::size_type. In a vector loop, use std::size_t, a range-based loop, or validate before converting.

Find the two operand types

A vector’s size() returns an unsigned size type. Comparing it with int mixes signed and unsigned operands and GCC warns under -Wall -Wextra. Newer GCC wording says “comparison of integer expressions of different signedness”; older versions may say “comparison between signed and unsigned integer expressions.” At /W4 on x64, MSVC does not warn here because int is narrower than the 64-bit std::size_t. /Wall reports C4388 for this comparison, but /Wall is off by default. MSVC reports C4018 at /W4 when both operands have the same width, such as int and unsigned int.

Failing C++17 example

#include <iostream>
#include <vector>

int main() {
    std::vector<int> values{4, 7, 9};
    for (int i = 0; i < values.size(); ++i) {
        std::cout << values[i] << '\n';
    }
    return 0;
}

GCC diagnostic core:

warning: comparison of integer expressions of different signedness

Here, the operands are an int index and the vector?s unsigned size type.

Fixed example

#include <cstddef>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> values{4, 7, 9};
    for (std::size_t i = 0; i < values.size(); ++i) {
        std::cout << values[i] << '\n';
    }
    return 0;
}

Expected output:

4
7
9

Stop an unsigned reverse loop

An unsigned index is always greater than or equal to zero. In this loop, i >= 0 remains true after decrement wraps the index, so the loop does not terminate and later accesses outside the vector. GCC warns with -Wall -Wextra.

Warning example

#include <cstddef>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> values{4, 7, 9};
    for (std::size_t i = values.size() - 1; i >= 0; --i) {
        std::cout << values[i] << '\n';
    }
    return 0;
}

GCC diagnostic core:

warning: comparison of unsigned expression in '>= 0' is always true

MSVC code: none. Do not run this case because the loop does not terminate.

Fixed example

#include <cstddef>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> values{4, 7, 9};
    for (std::size_t i = values.size(); i-- > 0;) {
        std::cout << values[i] << '\n';
    }
    return 0;
}

Expected output:

9
7
4

Know what the comparison does

When a negative int is compared with an unsigned value of a suitable rank, the negative value converts to unsigned. For example, -1 < values.size() is false when the conversion produces a large unsigned value. The comparison does not test whether -1 is a valid index. This conversion rule also affects equality and arithmetic, so inspect the operand types rather than guessing from their printed values.

Use the container size type

An indexed loop can declare std::size_t i = 0 and compare i < values.size(). Include for std::size_t. The strict less-than condition stops before the one-past-the-end position. Avoid decrementing an unsigned index below zero; it wraps to a large positive value. If the index must represent negative values, validate them before converting to an unsigned type.

Avoid an index when you do not need one

A range-based for loop visits each existing element without comparing an index to size(). This is often the clearest choice when the loop only reads or updates every element. Use an indexed loop when position matters, such as comparing neighbors or writing into a second sequence. The simplest loop type depends on the operation, not on suppressing a compiler message.

Convert only after checking

Sometimes an API requires int. First verify that the size fits in int, then convert explicitly. When an input index is signed, reject values below zero before converting it to std::size_t, and then check that it is smaller than size(). A cast alone can silence the warning while preserving a bug. Keep the range check close to the conversion and access.

Exercise

Replace the signed index with a loop that safely visits every vector value.

Broken program

#include <iostream>
#include <vector>

int main() {
    std::vector<int> values{2, 5};
    for (int i = 0; i < values.size(); ++i) std::cout << values[i] << '\n';
    return 0;
}

Compiler diagnostic core:

warning: comparison of integer expressions of different signedness

Sample input: none.

Expected output after the fix:

2
5

Hint 1: Compare the index type with size() result type. Hint 2: A range-based for loop avoids the index.

Show one possible solution
#include <iostream>
#include <vector>

int main() {
    std::vector<int> values{2, 5};
    for (int value : values) std::cout << value << '\n';
    return 0;
}

Expected output:

2
5

Keep learning with CppPath

Continue with the Loops lesson. The full lesson includes a quiz and a checked coding challenge with a free account.