在我正在阅读的《Pro C# 2008 和 .NET Platform》一书中,有一章是关于 CIL 的,其中有一些我感到困惑的代码。
为什么突出显示的步骤是必要的?据我所知,这就是代码正在做的事情。
- 创建局部整型变量“i”并将其初始化为 0(如果未显式赋值,则整数始终初始化为 0)
- (IL_0000) 局部变量 [0](即“i”)的值加载到堆栈中
- (IL_0001) 然后将该值从堆栈中弹出并再次分配给“i”。 。 。为什么? “i”已经是 0!
最佳答案
从内存的角度来看,您可以认为没有必要将 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 中元素的不同之处。
关于.net - 这个 CIL 代码是做什么的?为什么需要第3步?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5840020/