左移操作员的奇怪整体促销

时间:2013-06-02 05:59:22

标签: c++ c type-conversion

请参阅下面的代码,为什么没有文字“1”的整体推广?

long long n = 50;
long long a = 1 << n; // 262144
long long b = 1LL << n; // 1125899906842624

3 个答案:

答案 0 :(得分:10)

根据elazar的要求:

显示的结果是可接受的结果,因为移位会调用未定义的行为。这是因为普通1int,并且移位了int范围0..(sizeof(int) * CHAR_BIT)-1之外的值(通常为0..31)会导致未定义的行为。

请注意,移位的类型仅受(提升的)左操作数的类型的影响。这与(一次注意到chris)不同于大多数其他二元运算符,例如加法,其中两个操作数的类型影响结果的类型。当然,赋值的类型由左操作数的类型控制,如果需要,右边的值被强制转换为正确的类型(但是赋值的右边的值是在不参考它的类型的情况下计算的)将被分配给,如本例所示。)

ISO / IEC 9899:2011(C)

  

§6.5.7按位移位运算符

     

¶3对每个操作数执行整数提升。该   结果的类型是提升的左操作数的类型。如果右操作数的值为负或大于或等于提升的左操作数的宽度,则行为未定义。

ISO / IEC 14822:2011(C ++)

  

§5.8转换运算符

     

操作数应为整数或无范围的枚举类型,并执行整体促销。结果的类型是提升的左操作数的类型。

答案 1 :(得分:2)

以下是等效代码:

long long n = 50;
int x = 1;
x <<= n; // sizeof(x) is 4, probably. 32 bit. we are shifting it by 50.
long long a = x;

long long z = 1LL;
z <<= n;
long long b = z;

现在更清楚了吗?

答案 2 :(得分:2)

我怀疑你混合了整体促销通常的算术转换

整体促销将较小的积分操作数提升为intunsigned int类型。由于1已经是int,因此无法进一步推广。

通常的算术转换将二元运算符的操作数引入公共类型(例如,在二进制+的情况下发生),然后用于执行实际计算。我怀疑您希望这些转换发生在您的示例中,因为右侧操作数具有long long类型。即您可能希望将1转换为long long类型。但是,对于按位移位运算符,通常不执行通常的算术转换。它们是针对加法,乘法,关系运算符等执行的,但不适用于按位运算符。这就是1仍然是int并且代码触发未定义行为的原因。