这是一个当前在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位数据类型,我的单位也会被遗忘。但是我真的很困惑为什么调试版本会产生不同的输出,如果我将变量作为参数与常量相比移位?
答案 0 :(得分:5)
64位需要long long
类型。
对于操作数,表达式1 << 32
将使用int
类型进行求值,而不管分配此结果的变量的类型。
1LL << 32
和1LL << rot
会带来更多好运。这导致使用long long
类型评估表达式。
目前您的程序行为未定义,因为您在编写1 << 32
时过度调整了类型。另请注意,1 << 32
是编译时可评估的常量表达式,而1 << rot
不是。{1}}。这可能是使用变量和常数之间观察到的差异的原因。
答案 1 :(得分:3)
当1 << rot
为rot
时,int
表达式会为您提供int
结果。如果您将其放入long long
,因为损坏已经完成(a),这无关紧要。
改为使用1LL << rot
。
(a)而且,根据C11 6.5.7 Bitwise shift operators
,损坏是指未定义的行为:
对每个操作数执行整数提升。结果的类型是提升的左操作数的类型。如果右操作数的值为负 或大于或等于提升的左操作数的宽度, ,则行为未定义。
至于&#34;为什么调试版本会产生不同的输出,如果我将变量作为参数与常量&#34;相比,这是未定义行为的变幻莫测之一 - 字面意思是&# 39;允许发生。它完全有权使用derisive_laughter.ogg
并格式化您的硬盘: - )