Search code examples
c++vectorstdoutinteger-overflow

Weird behavior of vector.size() while printing to std output


I was solving a question when I encountered this behaviour and wasn't able to understand why it happened, any help would be appreciated.

vector<int> v1;
v1.push_back(0);
    
int no = v1.size() - 3;
// this prints output as expected  -> -2
cout << no << endl;
    
// this prints -> 18446744073709551614
cout << v1.size() - 3;

This is something about integer overflow, but I know nothing further.


Solution

  • The size of standard containers is represented as an unsigned integer (when using the default allocator such as in the example). Unsigned integer can represent only non-negative numbers.

    When one operand of binary arithmetic operation (subtraction in this case) is unsigned (and at least as ranked as int) and the other is signed of same or lower rank, then the signed operand will be converted to the unsigned type. The result of the operation is that same type.

    So, since the result of the operation is an unsigned integer, it cannot possibly be a negative number because those are not representable by unsigned integers. What happened is that the "correct" result of the operation was outside of representable numbers. This can happen both when the value is below representable range of values as well as above.

    When "correct" result of unsigned arithmetic operation is outside representable range, the adjusted result that you get will be a representable value that is congruent with the "correct" result modulo M which is the number of representable values of the type (M == 2number of bits). In this case 18446744073709551614 is congruent with -2 modulo M.


    Note that when result of signed arithmetic is outside the range of representable values, then the behaviour of the program is undefined. It is important to avoid that.