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

时间:2015-11-13 09:14:55

标签: c# operators cil comparison-operators

所以我看一下ILDASM,检查一个看起来像这样的.exe:

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

}

现在,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

我知道第一个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

2 个答案:

答案 0 :(得分:3)

ceq从堆栈中获取两个值,如果认为它们相等则会生成1,如果不是0则生成==。但是,C#中的ceq是否会产生==取决于很多事情:

  • 数据类型
    • 他们是灵长类动物吗?
    • 他们是否有自定义bne.un.s运营商?
    • 他们是参考吗?
  • 上下文
    • 可以优化其他东西吗? (我在类似的示例中得到beq*;还有br*switch$arr = array(array("x"=>145, "y"=>20),array("x"=>145, "y"=>40)); 等)
    • 可以完全删除吗?

答案 1 :(得分:1)

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

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

给我:

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         

从IL_0005开始,我们有:

加载b
加载1
ceq(如果相等,请按1,如果误推0) - 此处的结果为1
加载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;