Search code examples
c++visual-c++integer-overflowunsigned-long-long-int

Unsigned long long overflow error?


I have been having some strange issues with unsigned long long.

It happens when I set an unsigned long long (I used size_t, however the problem is repeatable with u-l-l). I have set it to 2^31, however for some reason it reverts to 18446744071562067968, or 2^64 - 2^31. Keep in mind I am using an x64 compilation:

unsigned long long a = 1 << 31;
cout << a;

//Outputs 18446744071562067968, Expected 2147483648

I thought the limits of u-l-l were 2^64-1? So why can 2^31 not be stored? 2^30 works just fine. Sizeof(a) returns 8, which is 64 bits if I am not mistaken, proving the limit of 2^64-1.

I am compiling on Visual C++ 2013 Express Desktop.

My only guess is that it is some type of overflow error because it doesn't fit a normal long type.


Solution

  • What you're seeing is sign extension when the negative integer value is assigned to the unsigned long long.

    To fix it you need to make the value unsigned to begin with, something like this:

    #include <iostream>
    #include <iomanip>
    
    int main()
    {
        unsigned long long a = 1ull << 31ull;
        std::cout << a << "\n";
        std::cout << std::hex << a << "\n";
    
        return 0;
    }
    

    If you have the warning level set high enough (/W4) you'd see a warning about the signed/unsigned mismatch.

    Just to be complete, you don't need to qualify both arguments, just the left operand is fine, so unsigned long long a = 1u << 31; would work. I just prefer to be as explicit as possible.