我想设置一个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位翻转了。我是否遗漏了编译器设置?任何帮助都非常感谢。
2条答案
按热度按时间k7fdbhmy1#
你的编译器应该警告过你。
在此行中:
1
是一个int
文字(int
通常是32位)。例如,在MSVC中,我得到:
警告C4334:“〈〈”:32位移位的结果隐式转换为64位(是否要进行64位移位?)
您应该将其更改为:
现在,您将获得预期的输出。
soat7uwm2#
我是否缺少编译器设置?
我认为您忽略了
1
是int
,并且sizeof(int)
可以小于sizeof(uint64_t)
,将32位值左移超过31位会产生不是特别有用的结果。如果您将
1
替换为1ULL
,或者替换为((uint64_t)1)
,您将得到更符合您期望的行为。