这个CIL代码在做什么?为什么第三步是必要的?

时间:2011-04-30 06:25:54

标签: .net for-loop cil

在我正在阅读_Pro C#2008和.NET平台的书中,有一章关于CIL,其中包含一些令我困惑的代码。

enter image description here

为什么要突出显示步骤?正如我所看到的,这就是代码正在做的事情。

  1. 创建一个本地整数变量“i”并初始化为0(如果未明确赋值,整数总是初始化为0)
  2. (IL_0000)将局部变量[0](即“i”)的值加载到堆栈中
  3. (IL_0001)然后将值从堆栈中弹出并再次分配给“i”。 。 。为什么? “我”已经是0了!

1 个答案:

答案 0 :(得分:4)

从内存的角度来看,你可以考虑将i初始化为0,因为初始化的int32变量的默认值是0。

但是,编译器在源代码中保留了循环的语义信息。毕竟,变量i在for语句中被赋值为0,并且该信息最终在IL中被序列化。无论如何,这个声明很可能会被JIT优化掉。至少Mono的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中元素的不同很容易。