我一直在尝试在业余时间学习C语言,其他语言(C#,Java等)具有相同的概念(通常是相同的运算符)......
我想知道是,在核心层,是什么位移(<<,>>,>>>)这样做,可以帮助它什么问题解决,和周围的弯曲什么潜伏的陷阱?换句话说,一个绝对的初学者指导比特移位的所有优点.
在2014年之前的所有C和C++版本中,写作
1 << (CHAR_BIT * sizeof(int) - 1)
Run Code Online (Sandbox Code Playgroud)
导致未定义的行为,因为左移定义为等效于连续乘法2,并且此移位导致有符号整数溢出:
结果
E1 << E2是E1左移位E2位置; 腾出的位用零填充.[...]如果E1有一个带符号的类型和非负值,并且结果类型中可以表示E1×2 E2,那么这就是结果值; 否则,行为未定义.
但是在C++ 14中,文本已经改变<<但不是为了乘法:
值
E1 << E2是E1左移位E2位置; 空位是零填充的.[...]否则,如果E1有一个有符号类型和非负值,并且E1×2 E2可以在结果类型的相应无符号类型中表示,那么转换为结果类型的那个值就是结果值; 否则,行为未定义.
现在的行为与签名类型的超出范围分配相同,即[conv.integral]/3所涵盖的行为:
如果目标类型已签名,则如果可以在目标类型(和位字段宽度)中表示该值,则该值不会更改; 否则,该值是实现定义的.
这意味着它仍然是不可移植的1 << 31(在具有32位int的系统上).那么为什么在C++ 14中做出这种改变呢?
int z = 1;
z <<= 31;
z >>= 31;
printf ("%d\n",z);
Run Code Online (Sandbox Code Playgroud)
当我运行代码时z=-1,为什么?