当您将Int32设置为Int16时,幕后会发生什么?

时间:2009-08-27 05:32:43

标签: c# .net runtime

当我这样做时,什么情况发生在低水平?

Int32 a = 0;
Int16 b = 50;

a = b;

3 个答案:

答案 0 :(得分:7)

这样的事情:

IL_0001:  /* 1F   | 32               */ ldc.i4.s   50
IL_0003:  /* 0B   |                  */ stloc.1
IL_0004:  /* 07   |                  */ ldloc.1
IL_0005:  /* 0A   |                  */ stloc.0

在较低级别,它取决于机器架构和优化级别。像这样的代码,没有任何影响,可能只是完全省略。否则,它将是简单的代码,也许是这样:

movsx eax, word ptr [ebp+12]
mov [ebp+8], eax

movsx是x86指令,当它被加载到更大的目的地时保留较短数字的符号;基本上,它会查看较小源的最高位,并在扩展数字时将其复制到剩余的位中。

答案 1 :(得分:2)

来自Reflector:

.method public hidebysig static void Main() cil managed
{
    .entrypoint
    .maxstack 1
    .locals init (
        [0] int32 num,
        [1] int16 num2)
    L_0000: nop 
    L_0001: ldc.i4.0          ; Load the constant 0
    L_0002: stloc.0           ; Store the value into local var 0
    L_0003: ldc.i4.s 50       ; Load the constant 50 - notice it treats it as a 32-bit value
    L_0005: stloc.1           ; Store the value into local var 1
    L_0006: ldloc.1           ; Load local var 1
    L_0007: stloc.0           ; Store the value into local var 0
    L_0008: ret 
}

在IL级别,赋值中没有任何特殊情况,但请注意ldc.i4.s 50将字面值视为4字节(32位)整数。

当代码是JIT编译时,生成的汇编代码可能只是将值50提升到32位宽的值。

答案 2 :(得分:0)

评估堆栈的表示形式不小于32位。 [编辑,在大多数情况下(感谢评论更新:)]直到你实际存储除堆栈之外的其他地方的16位值,没有特殊发生,因为shortint的大小相同。以下是您将看到差异的唯一操作:

  • b = (short)a
    将结果的第16位符号扩展为完整的32位宽变量。这是评论中提到的conv.i4指令。
  • *(short*)c = b 分配给结构成员,其结构标记为StructLayout.Explicit或包装小于4.
    只会写出其32位表示的低16位。
  • checked { b = (short)a; }
    如果(a < -32768 || a > 32767)
  • 将抛出异常