代码之家  ›  专栏  ›  技术社区  ›  Mr Anderson

按大于数据类型大小的值进行的位移位操作[重复]

  •  1
  • Mr Anderson  · 技术社区  · 7 年前

    考虑以下代码:

    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
    

    它不会生成警告(关于使用大于32的移位),因此它必须是预期的行为。

    实际输出到生成的程序集(或至少是反射器对代码的解释)的代码是

     uint val = 1;
     uint shift31 = val << 0x1f;
     uint shift32 = val;
     uint shift33 = val << 1;
     uint shift33a = val << 0x21;  
    

    IL(再次使用反射器)为

    L_0000: nop 
    L_0001: ldc.i4.1 
    L_0002: stloc.0 
    L_0003: ldloc.0 
    L_0004: ldc.i4.s 0x1f
    L_0006: shl 
    L_0007: stloc.1 
    L_0008: ldloc.0 
    L_0009: stloc.2 
    L_000a: ldloc.0 
    L_000b: ldc.i4.1 
    L_000c: shl 
    L_000d: stloc.3 
    L_000e: ldloc.0 
    L_000f: conv.u8 
    L_0010: ldc.i4.s 0x21
    L_0012: shl 
    L_0013: conv.u4 
    L_0014: stloc.s shift33a
    

    我理解 什么 正在进行(如中所述 MSDN ); 在编译代码时,在移位32位值时仅使用较低的5位。。。我很好奇 为什么? 这种情况会发生。

    (方式 shift33a 《出来》也让我觉得反射器有些地方不太对劲,因为他们对IL的c#表示将编译成不同的东西)

    问题:

    • 为什么? 是否仅使用“移位值”的低位5位?
    • 如果“移位超过31位没有意义”,为什么没有警告?
    • 这是向后兼容的事情吗(即,这是程序员“期望”发生的事情)?
    • 底层IL可以进行超过31位的移位(如 L_0010: ldc.i4.s 0x21 )但是编译器正在修剪这些值?
    0 回复  |  直到 17 年前