Что делает этот код CIL?Зачем нужен третий шаг? - PullRequest
2 голосов
/ 30 апреля 2011

В книге, которую я читаю _Pro C # 2008 и .NET Platform "есть глава о CIL с некоторым кодом, который меня смущает.

enter image description here

Почемуявляется ли выделенный шаг необходимым? Как я понимаю, именно это и делает код.

  1. Создается локальная целочисленная переменная "i", которая инициализируется значением 0 (в силу того, что целые числа всегда инициализируютсяв 0, если явно не присвоено значение)
  2. (IL_0000) Значение локальной переменной [0] (то есть «i») загружается в стек
  3. (IL_0001) Затемзначение выталкивается из стека и снова присваивается "i" ... ПОЧЕМУ? "i" уже 0!

1 Ответ

4 голосов
/ 30 апреля 2011

С точки зрения памяти, вы можете считать инициализацию i равной 0 ненужной, поскольку значение по умолчанию для инициализированной переменной int32 равно 0.

Однако компилятор сохраняет семантическую информацию о цикле в исходном коде. В конце концов, переменная i присваивается 0 в операторе for, и эта информация заканчивается сериализацией в IL. Вполне вероятно, что это утверждение будет оптимизировано JIT в любом случае. По крайней мере, JIT Моно делает это. С точки зрения CIL легко увидеть, что происходит:

.locals init (int32 i)

ldc.i4.0
stloc.0

// i = 0

br.s loop_test

loop_body:
    ldloc.0
    ldc.i4.1
    add
    stloc.0

    // i = i + 1

loop_test:
    ldloc.0
    ldc.i4.s  10
    blt.s loop_body

    // i < 10  

ret

На уровне CIL значение for в основном:

  • предварительно протестированный цикл (условие проверяется перед первым выполнением тела, следовательно, br, безусловная ветвь),
  • инициализаторы переменных перед телом цикла,
  • операции над инициализированными переменными в конце тела.

Довольно просто визуально идентифицировать различные элементы в CIL выше.

...