c++ 使用uint64_t的困难

j0pj023g  于 2022-12-20  发布在  其他
关注(0)|答案(2)|浏览(329)

我想设置一个64位数字中的各个位,并认为uint64_t非常适合这项工作。我遇到了一些奇怪的问题,所以我做了一些实验:
我编写了以下测试程序:

#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;
}

输出结果让我大吃一惊:

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

我测试了最大值(std::cout << hex << std::numeric_limits<uint64_t>::max() << std::endl),结果ffffffffffffffff符合预期。
我在Fedora 37上运行gcc 12.2.1。
看起来我的unsigned int在第31位变成了signed并且在第32位翻转了。我是否遗漏了编译器设置?任何帮助都非常感谢。

k7fdbhmy

k7fdbhmy1#

你的编译器应该警告过你。
在此行中:

test_value = (1 << i);

1是一个int文字(int通常是32位)。
例如,在MSVC中,我得到:
警告C4334:“〈〈”:32位移位的结果隐式转换为64位(是否要进行64位移位?)
您应该将其更改为:

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

现在,您将获得预期的输出。

soat7uwm

soat7uwm2#

我是否缺少编译器设置?
我认为您忽略了1int,并且sizeof(int)可以小于sizeof(uint64_t),将32位值左移超过31位会产生不是特别有用的结果。
如果您将1替换为1ULL,或者替换为((uint64_t)1),您将得到更符合您期望的行为。

相关问题