左移的一些意外行为<<

Somewhat unexpected behaviour from left shift <<

这是一个 32 位 MFC 应用程序,当前 运行 Windows 10。使用 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 位数据类型,显然我的单个位被左移到遗忘了。但我真的很困惑,如果我将变量作为参数与常量进行转换,为什么调试版本会产生不同的输出?

您需要 long long 64 位类型。

表达式 1 << 32 将使用 int 类型的操作数进行计算,无论此结果分配给的变量类型如何。

1LL << 321LL << rot 你会更有运气。这会导致使用 long long 类型对表达式进行求值。

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

表达式 1 << rot,当 rotint 时,将得到 int 结果。将它放入 long long 中并不重要,因为损坏已经完成(a).

改用1LL << rot


(a) 而且,根据 C11 6.5.7 Bitwise shift operators:

,我所说的损坏是指未定义的行为

The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.

至于 "why the debug build produces different outputs if I shift with a variable as a parameter compared to a constant",那是变幻莫测的未定义行为之一——实际上任何可能发生的事情都允许发生。它完全有权播放 derisive_laughter.ogg 和格式化您的硬盘:-)