我曾经是Windows上的C++程序员。
我知道编译器将优化C++中的三元运算符。

C++代码:

#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
    int result = argc > 3 ? 1 : 5;
    printf("%d", result);
    return 0;
}

由于管道的原因,生成的 native 代码如下所示(当然是版本模型):
int result = argc > 3 ? 1 : 5;
00B21003  xor         eax,eax
00B21005  cmp         dword ptr [argc],3
00B21009  setle       al
00B2100C  lea         eax,[eax*4+1]

C#代码:
namespace TernaryOperatorCSharp
{
    static void Main(string[] args)
    {
        int argc = args.Length;
        int result = argc > 1 ? 2 : 5;
        System.Console.WriteLine(result);
    }
}

我查找了JIT生成的 native 代码,但是根本没有优化(还有两个跳转指令)。
int result = argc > 1 ? 2 : 5;
0000002f  cmp         dword ptr [ebp-4],1
00000033  jg          0000003F
00000035  nop
00000036  mov         dword ptr [ebp-0Ch],5
0000003d  jmp         00000046
0000003f  mov         dword ptr [ebp-0Ch],2
00000046  mov         eax,dword ptr [ebp-0Ch]
00000049  mov         dword ptr [ebp-8],eax
System.Console.WriteLine(result);
0000004c  mov         ecx,dword ptr [ebp-8]
0000004f  call        6A423CBC

为什么C#JIT编译器不进行与C++编译器相同的优化?

这背后的故事是什么?

任何信息将不胜感激。

嗨,您好,
我已经修改了C#程序,并使用发布模型运行它。

之前
int result = args.Length > 1 ? 2 : 5;

现在
int argc = args.Length;
int result = argc > 1 ? 2 : 5;

但是结果仍然是一样的。
仍然存在两个跳转指令。
如果有更多详细信息,我们将不胜感激。

最佳答案

您没有在进行优化编译-nop指令指示了这一点(编译器将其插入以用作 anchor ,以便可以在大括号上放置断点)。

即使选中了“优化代码”复选框,Visual Studio也不总是产生优化的代码。通常,当您在调试器中启动时,它会始终禁用优化,因此调试 session 的行为会超出您的预期。

此外,您没有将苹果与苹果进行比较,因为苹果占了大部分。
string[].Length是C#中的属性,不是公共(public)变量,而且不是局部变量。通过使用代码,通常将属性视为公共(public)变量,但实际上,它们可以作为成熟的get/set方法存在。编译器必须发出代码来处理此问题,尤其是在单独的程序集中定义了Property的情况下。

尝试使用本地int变量并打开编译器优化的示例(使用优化进行构建,启动程序,在启动后附加调试器,查看反汇编)。

关于c# - C#与C++三元运算符,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20827111/

10-11 21:12