为什么优化的 IL 会在保存变量中存储相同的值两次



源代码是一个 for 循环,如下所示:

public class ForLoop
{
    public static void Main()
    {
        var count = 0;
        for (var i = 0; i < 10; i = i++)
        {
            count++;
        }
    }
}

我已经在打开优化的情况下编译了它(csc /o+ ForLoop.cs),但是IL有一个dup,然后是两个stloc.1和一个ldloc.1

.method public hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       22 (0x16)
  .maxstack  3
  .locals init (int32 V_0,
           int32 V_1)
  IL_0000:  ldc.i4.0
  IL_0001:  stloc.0
  IL_0002:  ldc.i4.0
  IL_0003:  stloc.1
  IL_0004:  br.s       IL_0010
  IL_0006:  ldloc.0
  IL_0007:  ldc.i4.1
  IL_0008:  add
  IL_0009:  stloc.0
  IL_000a:  ldloc.1
  IL_000b:  dup
  IL_000c:  ldc.i4.1
  IL_000d:  add
  IL_000e:  stloc.1
  IL_000f:  stloc.1
  IL_0010:  ldloc.1
  IL_0011:  ldc.i4.s   10
  IL_0013:  blt.s      IL_0006
  IL_0015:  ret
} // end of method ForLoop::Main

作为IL_000b的指令复制了 my for 循环中的 i 变量。 然后它加 1,存储结果,所以堆栈上剩下的是我的原始值 i ,预加。 然后,它再次存储它,并再次加载它。

这感觉不是最佳的,甚至不正确。

那么它为什么要这样做呢?

首先

,你必须明白i++实际上是三个操作:

  1. 获取i的值

  2. 向值添加 1 并存储它。

  3. 将新值推回 i

其次,你的代码是错误的。你的循环有i = i++(而不是通常的简单i++),这就是为什么你会看到额外的两个作业。

您正在执行提到的三个步骤,即存储i++的结果,然后将其推送回i

相关内容

  • 没有找到相关文章

最新更新