为什么1ul<< 64返回1而不是0? [英] Why does 1ul << 64 return 1 instead of 0?

查看:311
本文介绍了为什么1ul<< 64返回1而不是0?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑下面的一段代码:

  // //直接循环直到64被命中。 
unsigned long x = 0; (i == 64){
x = 1ul<<<<一世;
printf(x:%d \\\
,x);




$ b我们知道unsigned long是64位宽的,并且向左移动64个位置将变为1000 ... 000(在一个之后64个零),并且已经被截断为0。 p $ p> x:1

奇怪的是,如果我们只是(

  printf 

它会打印0.



可以任何人都解释为什么会发生这种情况为什么在第一种情况下,程序错误地产生1而不是0,但在第二种情况下,它是正确的?

解决方案

移动宽度或更多的类型会导致未定义的行为根据§6.5.7/ 3:



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


基本原理是各种CPU实现不同的行为对于超大规模的班次,定义这种情况下的行为限制太多 - 很多班次都需要额外的程序集生成。 (虽然也许它应该是实现定义的而不是未定义的)。



您的观察可以通过使用Intel家族CPU来解释,该家族CPU在硬件上使用mod 64 64位类型的移位宽度,因此在运行时间 1ul<< 64 1ul<< 0 would;但在编译时在另一种情况下,编译器计算 1ul<< 64 使用算术规则。

Consider the following piece of code:

// Simply loop over until 64 is hit. 
unsigned long x = 0;
for (int i = 0; i <= 64; i++) {
  if (i == 64) {
    x = 1ul << i;
    printf("x: %d\n", x);
  }
}

We know that unsigned long is 64-bit wide, and left shifting 1 by 64 positions would become 1000...000 (64 zeros behind one), and would have been truncated to 0. However, the actual printout gives:

x: 1

The strange thing is, if we just do

printf("x: %d\n", (1ul << 64));

It would print 0.

Can anyone explain why this is happening? Why in the first case, the program mistakenly produces 1 instead of 0, but in the second case it's correct?

解决方案

Shifting by the width of a type or more causes undefined behaviour according to §6.5.7/3:

  1. The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.

The rationale for this is that various CPUs implement different behaviour for over-sized shifts and it would have been too restrictive to define behaviour for this case -- many shifts would need extra assembly generated. (Although perhaps it should have been implementation-defined rather than undefined).

Your observation could be explained by using Intel family CPU which in hardware does "mod 64" on the shift width for a 64-bit type, so at runtime 1ul << 64 did the same as 1ul << 0 would; but at compile-time in the other case the compiler computed 1ul << 64 using arithmetic rules.

这篇关于为什么1ul&lt;&lt; 64返回1而不是0?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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