c++uint64

Struggling with uint64_t


I want to set individual bits in a 64 bit number and figured that the uint64_t is ideal for the job. I ran into some strange problems, so I did some experiments:

I wrote the following test program:

#include <iostream>
#include <cstdint>
#include <iomanip>

int main()
{

    uint64_t test_value = 0;

    for( int i=0; i<63; ++i ) {
        test_value = (1 << i);
        std::cout << hex << test_value << "\n";
    }

    return 0;
}

The output surprised me:

1
2
4
8
10
... (irrelevant output elided)
10000000
20000000
40000000
ffffffff80000000
1
2
4
8
10
...
10000000
20000000
40000000

I tested the max value (std::cout << hex << std::numeric_limits<uint64_t>::max() << std::endl) resulting in ffffffffffffffff as expected.

I am running gcc 12.2.1 on Fedora 37.

It looks like my unsigned int changed to signed on bit 31 and rolled over on bit 32. Am I missing a compiler setting? Any help is greatly appreciated.


Solution

  • Your compiler should have warned you.
    In this line:

    test_value = (1 << i);
    

    1 is an int literal (and int is usully 32 bit).

    E.g. in MSVC I get:

    warning C4334: '<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)

    You should change it to:

    //-------------vvv-------
    test_value = (1ull << i);    // You can also use: (uint64_t)1 instead of 1ull
    

    And now you'll get the output you expect.