位移位编译器错误或极端情况

Bit shift compiler bug or a corner case?

本文关键字:情况 错误 编译器      更新时间:2023-10-16

以下代码输出0,1,32,33。这至少可以说是违反直觉的。但是,如果我将文字1替换为类型声明常量"ONE",则循环运行良好。

这是与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位。

<

解决方案/strong>

。& lt; & lt;不要求每一方都有相同的类型。毕竟,当最大的移位可以在char中使用时,为什么要将右侧设置为int64_t呢?提升只在处理算术运算符时发生,而不是在处理所有运算符时。

摘自Bill下面的评论

这是一个问题:(1<<k) .

1是一个整型字面值,适合于int

如果int在您的平台上小于64位,那么当k较大时,(1<<k)将在循环结束时具有未定义的行为。在你的例子中,编译器使用的是Intel的位移指令,未定义的行为就像Intel定义的大于操作数大小的移位一样——高位被忽略。

你可能想要(1LL<<k)


标准内容(expr.shift章节5.8):

操作数必须为整型或无作用域枚举类型,并执行整型提升。结果的类型是提升后的左操作数的类型。如果右操作数为负,或大于或等于提升后的左操作数的位长度,则未定义该行为。

这与"执行通常的算术转换"的措辞形成对比算术或枚举类型的操作数",用于加法和减法运算符

该语言在c++ 03和c++ 11之间没有变化

相关文章: