以下代码输出 0,1,32,33。至少可以说这是违反直觉的。但是,如果我用类型注释常量“ONE”替换文字 1,则循环运行正常。
这是使用 gcc 4.6.2 和 -std=c++0x 的情况。
#include<iostream>
#include<cstdint>
using namespace std;
int main()
{
int64_t bitmask = 3;
int64_t k;
const int64_t ONE = 1;
cout<<"bitmask = "<<bitmask<<endl;
for(k=0; k<64; k++)
{
if(bitmask & (1<<k))
{
cout<<"k="<<k<<endl;
}
}
return 0;
}
EDIT
问题:正如 Ben 指出的,默认情况下 1 被视为 32 位宽。当它的合作数是 64 位时,为什么它没有提升到 64 位。
SOLUTION
不。
复制自下面 Bill 的评论
这是个问题:(1<<k)
.
1
是一个整数文字,适合int
.
If int
您的平台上的位数少于 64 位,那么(1<<k)
在循环结束时将有未定义的行为,当k
很大。在您的情况下,编译器正在使用英特尔位移指令,并且未定义的行为是通过英特尔定义大于操作数大小的移位的方式产生的 - 高位被忽略。
你可能想要(1LL<<k)
标准的内容(第 5.8 节expr.shift
):
操作数应为整型或无作用域枚举类型,并执行整型提升。结果的类型是提升后的左操作数的类型。如果右操作数为负,或者大于或等于提升的左操作数的位长度,则行为未定义。
这与“通常的算术转换是针对
算术或枚举类型的操作数。”它用于例如加法和减法运算符。
这种语言在 C++03 和 C++11 之间没有变化。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)