位移编译器错误还是极端情况? [英] Bit shift compiler bug or a corner case?

查看:73
本文介绍了位移编译器错误还是极端情况?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码输出0、1、32、33.至少可以说这是反直觉的.但是,如果我将文字1替换为带注释的常量"ONE",则循环运行良好.

The following code outputs 0,1,32,33. Which is counter intuitive to say the least. But if I replace the literal 1 with the type annonated constant "ONE", the loop runs fine.

这是与gcc 4.6.2和-std = c ++ 0x一起使用的.

This is with gcc 4.6.2 and -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位.

EDIT Question: As Ben pointed out, 1 is seen to be 32 bit wide by default. Why is it not promoted to 64 bits when it's co-operand is 64 bits.

解决方案

不.<<不需要每一侧都具有相同的类型.毕竟,当可用的最大移位量适合char时,为什么将右侧设置为int64_t?仅当您使用算术运算符而不是所有运算符时,促销才会发生.

No. << does not require that each side have the same type. After all, why make the right side an int64_t when the maximum shift available fits in a char? The promotion only occurs when you are dealing with arithmetic operators, not all operators.

从Bill的以下注释中复制

推荐答案

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

1 是一个整数文字,适合 int .

1 is a integral literal that fits in an int.

如果您平台上的 int 少于64位,则当(1<< k)到循环结束时将具有未定义的行为> k 很大.在您的情况下,编译器使用Intel位移位指令,并且未定义的行为以Intel定义的移位大于操作数大小的方式出现-高位将被忽略.

If int has fewer than 64 bits on your platform, then (1<<k) will have undefined behavior toward the end of the loop, when k 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.

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

标准所说的内容(第5.8节 expr.shift ):

What the standard says (section 5.8 expr.shift):

操作数应为整数或无范围枚举类型,并执行整数提升.结果的类型是提升后的左操作数的类型.如果右操作数为负或大于或等于提升后的左操作数的位长度,则该行为是不确定的.

The operands shall be of integral or unscoped enumeration type and integral promotions are performed. The type of the result is that of the promoted left operand. The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand.

这与通常的算术转换是针对算术或枚举类型的操作数.",例如加减运算符.

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.

这种语言在C ++ 03和C ++ 11之间没有变化.

This language didn't change between C++03 and C++11.

这篇关于位移编译器错误还是极端情况?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆