==运算符到底是做什么的?

Wil*_*lsu 5 c# cil operators comparison-operators

所以我看看ILDASM,检查一个如下所示的.exe:

int a = 2;
Int32 b = 1;
if(b == 1)
{

}
Run Code Online (Sandbox Code Playgroud)

现在,CIL代码看起来像这样:

IL_0005:  ldloc.1
IL_0006:  ldc.i4.1
IL_0007:  ceq
IL_0009:  ldc.i4.0
IL_000a:  ceq
IL_000c:  stloc.2
Run Code Online (Sandbox Code Playgroud)

我知道第一个b被加载(存储在[1]中),然后是一个值为1的常量,然后进行比较.我不明白的是为什么在存储比较结果之前加载并比较另一个值为0的常量.
由于第一次比较应该已经产生了一个真值,检查这个值是否为0会反转结果,对吧?
我现在的问题是:它为什么倒置了?我假设它与我使用的==运算符有关,我的理论是它返回差异.如果此差值为0,则值相同,因此应该是结果.但0表示错误,因此需要反转.
我似乎无法找到关于这个主题的任何内容,只是关于像==〜或类似的运算符.希望你能赐教:)

最好的祝福

Wilsu

PS:这是完整的代码:

.method private hidebysig instance void  Form1_Load(object sender,
                                                class [mscorlib]
System.EventArgs e) cil managed
{
// Code size       19 (0x13)

.maxstack  2
.locals init ([0] int32 a,
       [1] int32 b,
       [2] bool CS$4$0000)
IL_0000:  nop
IL_0001:  ldc.i4.2
IL_0002:  stloc.0
IL_0003:  ldc.i4.1
IL_0004:  stloc.1
IL_0005:  ldloc.1
IL_0006:  ldc.i4.1
IL_0007:  ceq
IL_0009:  ldc.i4.0
IL_000a:  ceq
IL_000c:  stloc.2
IL_000d:  ldloc.2
IL_000e:  brtrue.s   IL_0012
IL_0010:  nop
IL_0011:  nop
IL_0012:  ret
} // end of method Form1::Form1_Load
Run Code Online (Sandbox Code Playgroud)

Rob*_*Rob 1

据我所知,它正在跳转到函数的末尾。

void Main()
{
    int a = 2;
    Int32 b = 1;
    if(b == 1)
    {
        Console.WriteLine("A");
    }
}
Run Code Online (Sandbox Code Playgroud)

给我:

IL_0000:  nop         
IL_0001:  ldc.i4.2    
IL_0002:  stloc.0     // a
IL_0003:  ldc.i4.1    
IL_0004:  stloc.1     // b
IL_0005:  ldloc.1     // b
IL_0006:  ldc.i4.1    
IL_0007:  ceq         
IL_0009:  ldc.i4.0    
IL_000A:  ceq         
IL_000C:  stloc.2     // CS$4$0000
IL_000D:  ldloc.2     // CS$4$0000
IL_000E:  brtrue.s    IL_001D
IL_0010:  nop         
IL_0011:  ldstr       "A"
IL_0016:  call        System.Console.WriteLine
IL_001B:  nop         
IL_001C:  nop         
IL_001D:  ret         
Run Code Online (Sandbox Code Playgroud)

从 IL_0005 开始,我们有:

加载b
加载1
ceq(如果相等,则 Push 1,如果 false Push 0) - 这里的结果将是1
Load 0
ceq- 这里的结果将是0
brtrue.s IL_001D- 如果值非零,则跳转到IL_001D(函数结束)

所以它本质上是编译成这样的:

int a = 2;
Int32 b = 1;
if(!(b == 1))
    goto end;
Console.WriteLine("A");
:end
return;
Run Code Online (Sandbox Code Playgroud)

  • 对于上下文,当我编译这个(优化)时,我得到:`ldc.i4.1`,`ldc.i4.1`,`bne.un.s {to the ret}`,`ldstr "A"`,`调用 void [mscorlib]System.Console::WriteLine(string)`、`ret` - 非常不同 (2认同)