1

这是目前在 Windows 10 上运行的 32 位 MFC 应用程序。使用 Visual C++ 2013 编译。

std::cout << "sizeof(long long) = " << sizeof(long long) << std::endl;

int rot{ 32 };
long long bits{ (1 << rot) };
std::cout << "bits with variable = " << bits << std::endl;

long long bits2 = (1 << 32);
std::cout << "bits2 with constant = " << bits2 << std::endl;

system("pause");

long long 的大小是 8 个字节,足以管理我的 32 位,我在想。这是调试版本的输出:

sizeof(long long) = 8
bits with variable = 1
bits2 with constant = 0
Press any key to continue . . .

这是发布版本的输出:

sizeof(long long) = 8
bits with variable = 0
bits2 with constant = 0
Press any key to continue . . .

所以,很明显,即使是 64 位数据类型,我的单个位也会被左移到遗忘状态。但是我真的很困惑,如果我将变量作为参数与常量相比,为什么调试构建会产生不同的输出?

4

2 回答 2

5

你需要一个long long64 位的类型。

表达式1 << 32将使用int操作数的类型进行评估,而与分配此结果的变量的类型无关。

1LL << 32和,你会有更多的运气1LL << rotlong long这会导致使用类型对表达式进行评估。

目前,您的程序的行为是未定义的,因为您在编写1 << 32. 另请注意,这1 << 32是一个编译时可评估的常量表达式,而1 << rot不是。这可能解释了使用变量和常量之间观察到的差异。

于 2017-09-07T13:18:36.587 回答
3

表达式1 << rot, whenrotint, 会给你一个int结果。然后将其放入 a 中并不重要,long long因为损坏已经造成(a)

改为使用1LL << rot


(a)而且,我所说的损害是指未定义的行为,根据C11 6.5.7 Bitwise shift operators

对每个操作数执行整数提升。结果的类型是提升的左操作数的类型。如果右操作数的值为负数或大于或等于提升的左操作数的宽度,则行为未定义。

至于“如果我将变量作为参数与常量相比,为什么调试构建会产生不同的输出”,这是未定义行为的变幻莫测之一——实际上任何可能发生的事情都被允许发生。derisive_laughter.ogg播放和格式化硬盘完全在其权利范围内:-)

于 2017-09-07T13:22:30.040 回答