编译器魔术:为什么?

Joh*_*lph 11 c# compiler-construction optimization

我刚才注意到给出以下代码:

if (x.ID > 0 && !x.IsCool)
Run Code Online (Sandbox Code Playgroud)

Microsoft C#3.0(VS2008 SP1)编译器将优化它:

if (!((x.Id <= 0) || x. IsCool))
Run Code Online (Sandbox Code Playgroud)

这是在启用优化的Debug构建中.为什么编译器会这样做?它在执行方面更快吗?

我用Reflector找到了(我实际上是在寻找不同的东西)

Meh*_*ari 49

C#编译器肯定不会为您的代码段生成等效的C#代码.它编译成IL.基本上,你所看到的(来自Reflector,我猜)是反编译器为该IL吐出的等效C#代码.

  1. 语言规范没有说明"未经优化"的代码是什么.允许C#编译器生成任何有效的,功能相同的代码.即使没有优化开关,编译器也可以进行基本优化.除了这一点,你不能说什么是自然的编译器是否编译器优化故意与否.

  2. 整个if语句根据"and"子句中指定的每个单独表达式的值计算为一系列条件分支.使用"和"指令在单个代码块中计算表达式.反编译器的输出是从这些分支推断出来的.反编译器不能总是推断你写的原始表达式.它只输出相当的东西.

同样,这个片段之间的区别:

if (a) { something(); }
else { somethingElse(); }
Run Code Online (Sandbox Code Playgroud)

这个片段:

if (!a) { somethingElse(); }
else { something(); }
Run Code Online (Sandbox Code Playgroud)

通过查看已编译的代码,您无法区分.

  • +1这是正确的答案,并简洁地解释了引导.:) (3认同)

Bri*_*ian 8

我认为从语义语义的角度来看,这两个表达式完全相同.两种方式都涉及短路.

我有点大吃一惊,安德鲁的回答已经有十个赞成票; 这听起来像是胡说八道,但也许我真的错过了一些微妙的东西.

编辑

所以总结一下:

OP的问题是"为什么这种优化会发生".

事实上,没有"优化"发生.两个C#源代码在逻辑上是等价的.".Net Reflector"或其他任何反汇编工具也许可能将同一个IL反编译成一个或另一个.在IL级别,只有一堆条件跳转,所以没有必要知道"哪种方式是哪种方式,哪种方式是其他方式"或其他类似的DeMorgan等价方式.

令人着迷的是,人们非常乐意对这个问题的答案进行评论,即使(或者可能是因为)原始问题没有多大意义(或依赖于错误的假设).

令人高兴的是,最​​终人群的智慧(以及像@Mehrdad这样聪明的人)占上风.欢迎来到StackOverflow!

(我正在回答一个wiki,因为当代表被授予"问题的好答案"时,我不希望代表"讲述一个问题的故事".但我认为这个问题的故事很有趣.)

  • @Brian - 考虑到我100%不正确的事实,我也大吃一惊:)这就是我在不假思索地发布袖手旁观的结果. (3认同)

Ant*_*sma 6

if编译为条件跳转操作码.从表达式中提取否定允许通过使用通过块来交换条件跳转目标来优化它.