请考虑以下代码:
UInt32 val = 1;
UInt32 shift31 = val << 31; // shift31 == 0x80000000
UInt32 shift32 = val << 32; // shift32 == 0x00000001
UInt32 shift33 = val << 33; // shift33 == 0x00000002
UInt32 shift33a = (UInt32)((UInt64)val << 33); // shift33a == 0x00000000
Run Code Online (Sandbox Code Playgroud)
它不会生成警告(关于使用大于32的班次),因此它必须是预期的行为.
实际上被放到生成的程序集中的代码(或者至少是Reflector对代码的解释)是
uint val = 1;
uint shift31 = val << 0x1f;
uint shift32 = val;
uint shift33 = val << 1;
uint shift33a = val << 0x21;
Run Code Online (Sandbox Code Playgroud)
IL(再次,使用Reflector)是
L_0000: nop
L_0001: ldc.i4.1
L_0002: stloc.0 …Run Code Online (Sandbox Code Playgroud) 我现在对java左移操作有点困惑,
1<<31 = 0x80000000 --> this I can understand
Run Code Online (Sandbox Code Playgroud)
但
1<<32 = 1 Why is this?
1<<33 = 2
Run Code Online (Sandbox Code Playgroud)
看起来更多的移动值,采用模数32的值.
感谢大家的回复和JLS的报价.
我只想知道更多.知道它以这种方式设计的原因吗?或者只是一些惯例?显然C没有这个怪癖?
感谢@paxdiablo.看起来像C声明这个行为未定义.
我在这里有一些个人假设:
ARM体系结构参考手册A7.1.38
语法LSL Rd,Rm,#immed_5
哪里:
Rd 是存储操作结果的寄存器.
Rm是包含要移位的值的寄存器.
immed_5指定移位量,范围为0到31.
在指令级别,immedidate immed_5只需要5位就可以避免无意义的操作,从而节省一些指令空间.我想高级语言只是将这个约定统一起来,以避免在编译指令时产生无意义的努力.