位移位编译器错误还是特殊情况?
以下代码输出 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;
}
编辑 问题:正如 Ben 指出的那样,默认情况下 1 被视为 32 位宽。当它的合作数是 64 位时,为什么它没有提升到 64 位。
解决方案
编号<<不要求每一侧都具有相同的类型。毕竟,当可用的最大移位适合 char 时,为什么要将右侧设置为 int64_t 呢?仅当您处理算术运算符而不是所有运算符时才会发生提升。
复制自下面 Bill 的评论
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是一个问题:
(1<。
1
是适合int
的整数文字。如果
int
在您的平台上少于 64 位,则当k< 时,
(1< 在循环结束时将出现未定义的行为/code> 很大。在您的情况下,编译器正在使用英特尔位移指令,并且未定义的行为是通过英特尔定义大于操作数大小的移位的方式产生的 - 高位被忽略。
您可能想要
(1LL<
标准所说的内容(第 5.8 节
expr.shift
):这与“通常的算术转换是针对
算术或枚举类型的操作数。”,它存在于例如加法和减法运算符中。
这种语言在 C++03 和 C++11 之间没有改变。
This is a problem:
(1<<k)
.1
is a integral literal that fits in anint
.If
int
has fewer than 64 bits on your platform, then(1<<k)
will have undefined behavior toward the end of the loop, whenk
is large. In your case, the compiler is using an Intel bitshift instruction, and the undefined behavior comes out the way Intel defines shifts larger than the operand size -- the high bits are ignored.You probably want
(1LL<<k)
What the standard says (section 5.8
expr.shift
):This in contrast to the wording "The usual arithmetic conversions are performed for
operands of arithmetic or enumeration type." which is present for e.g. addition and subtraction operators.
This language didn't change between C++03 and C++11.