【发布时间】:2014-01-16 14:31:14
【问题描述】:
我曾经是 Windows 上的 C++ 程序员。 我知道编译器会优化 C++ 中的三元运算符。
C++ 代码:
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
int result = argc > 3 ? 1 : 5;
printf("%d", result);
return 0;
}
由于管道的关系,生成的原生代码如下图(当然是Release模型):
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 code,但是根本没有优化(还是两条跳转指令)。
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;
但结果还是一样。 还有两条跳转指令存在。 如果有更多信息,我将不胜感激。
【问题讨论】:
-
第一个条件大概是处理
args == null的情况,或者类似的情况。 -
JIT 也很可能认为没有理由优化此代码,因为它只运行一次。
-
嗯,这很容易检查,将代码粘贴在一个循环中。
-
也许答案是 C++ 是混合语言,具有结构类型,并且针对 ?运算符取自 C。而 C# 没有经典类型,int 是类。因此,运算符在该类定义中被重载。当你写 int result = args.Length > 1 ? 2:5;它正在调用 int 类中的方法
-
@RockLegend
int不是一个类,并且运算符没有在该类中定义(它们甚至是如何定义的?),int是 Special Magic 并且具有针对其运算符的 MSIL 指令(不打电话)。
标签: c# c++ ternary-operator