Что происходит за кулисами, когда вы устанавливаете Int32 равным Int16? - PullRequest
1 голос
/ 27 августа 2009

Что происходит на низком уровне, когда я это делаю?

Int32 a = 0;
Int16 b = 50;

a = b;

Ответы [ 3 ]

7 голосов
/ 27 августа 2009

Примерно так:

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, которая сохраняет знак более короткого числа при загрузке в большее место назначения; в основном он смотрит на самый значащий бит меньшего источника и копирует его в оставшиеся биты, когда расширяет число.

2 голосов
/ 27 августа 2009

От отражателя:

.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-битное значение.

0 голосов
/ 27 августа 2009

Стек оценки не имеет представления меньше 32-битного. [Изменить, в большинстве случаев (спасибо за обновление из комментария :)] До тех пор, пока вы на самом деле не сохраните 16-битное значение где-либо, кроме стека, ничего особого не происходит, потому что short и int имеют одинаковый размер. Вот единственные операции, в которых вы увидите разницу:

  • b = (short)a
    Признак расширит бит 16 результата до полной 32-битной переменной. Это инструкция conv.i4, упомянутая в комментарии.
  • *(short*)c = b или присваивание элементу структуры, где структура помечена StructLayout.Explicit или имеет упаковку меньше 4.
    Запишет только младшие 16 бит своего 32-битного представления.
  • checked { b = (short)a; }
    Будет сгенерировано исключение, если (a < -32768 || a > 32767).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...