左移的一些意外行为<<

时间:2017-09-07 13:16:39

标签: c++ visual-c++ visual-c++-2013

这是一个当前在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位数据类型,我的单位也会被遗忘。但是我真的很困惑为什么调试版本会产生不同的输出,如果我将变量作为参数与常量相比移位?

2 个答案:

答案 0 :(得分:5)

64位需要long long类型。

对于操作数,表达式1 << 32将使用int类型进行求值,而不管分配此结果的变量的类型。

1LL << 321LL << rot会带来更多好运。这导致使用long long类型评估表达式。

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

答案 1 :(得分:3)

1 << rotrot时,int表达式会为您提供int结果。如果您将其放入long long,因为损坏已经完成(a),这无关紧要。

改为使用1LL << rot

(a)而且,根据C11 6.5.7 Bitwise shift operators,损坏是指未定义的行为:

  

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

至于&#34;为什么调试版本会产生不同的输出,如果我将变量作为参数与常量&#34;相比,这是未定义行为的变幻莫测之一 - 字面意思是&# 39;允许发生。它完全有权使用derisive_laughter.ogg并格式化您的硬盘: - )