2013-07-11 93 views
11

我不知道为什么在下面的C#是罚款:为什么x ++ - + - ++ x合法但是x +++ - +++ x不是?

int y = x++-+-++x; 

int y = x+++-+++x; 

是不是?为什么对这个+有偏见?

+8

更好的问题是你为什么要使用它? – Sayse

+0

它取决于编译器(VS 2012上的.Net 4.5抱怨) –

+0

我们需要关于你正在使用的编译器,你所针对的是什么.NET等。 – tnw

回答

16

另外两个答案是正确的;我将增加他们,这说明了词法分析的一些基本原则:

  • 词法分析器是短视 - 它有少量的“前瞻”
  • 词法分析器是贪婪 - 它试图做出最长的令牌现在
  • 当一个失败时,词法分析器不会回溯试图寻找替代解决方案。

这些原则意味着+++x将lexed为++ + x而不是+ ++ x

然后解析器将解析++ + x++(+x),和(+x)不是可变,它是一个,所以它不能被递增。

另请参阅:http://blogs.msdn.com/b/ericlippert/archive/2010/10/11/10070831.aspx

+0

+1,尽管这会使它成为奇数Mono可以编译相同的代码。规范在这方面有点“开放”,或者其中一个编译器不太符合规范。 –

+2

@JoachimIsaksson:单声道有一个小错误;我怀疑它是在语义分析器中,而不是在词法分析器中。也就是说,它不是** Mono将'+++ x'作为'++ ++ x'的情况。相反,我怀疑它正确地把它当成'++ + x',然后语义分析器将'+ x'视为'x',但忘记'+ x'是一个值,而不是一个变量,因此不适合作为增量的操作数。 –

+0

@JoachimIsaksson:确实。 Microsoft C#编译器在C#2.0中有许多这类错误;我在C#3.0中删除了很多。我们保留的一些,因为它们是无害的,并采取突破性的变化将是破坏性的。 –

5

我正在使用VS 2012.这很有趣。

的第一个可以被解析成:

int y = (x++) - (+(-(++x))); 

而不改变最终的结果。所以你可以看到它为什么是有效的。

然而,第二个问题与+++x,因为(我猜)它看到两个++,并试图将该一元运算符应用于r值,这是另一个+(而不是有效的r值)。 您可以将它以各种方式,使其工作,但:

int y = (x++)+(-(+(++x))); 

是有效的。

我确定Jon Skeet或Eric Lippert或某人会出现并指出C#规范的相关部分。我甚至不知道从哪里开始。但是,只需遵循一般的从左到右的标记解析,就可以看到它将在第二个位置窒息的位置。

+0

仅供参考,附录中的整个语法都是规范的结尾。 –

+0

在操作符语法中看不到任何东西,但是在任何阶段是倾向于使用“+”还是“++”似乎都是模糊的。 –

+0

@JoachimIsaksson:规范的2.3节说*“当几个词法语法产生匹配源文件中的一系列字符时,词法处理总是形成最长的可能的词法元素。”* –

2

编译器在第二个++int y = x+++-+++x之后寻找变量或属性,并且无法确定没有空格或括号。

你可以这样做:

int y = x+++-+(++x); 

int y = x++ + -+ ++x; 

,如果你想要的。

你列出的第一个例子工作的原因是因为编译器可以确定从++x+-;而在第二个例子中,它不能确定将+++分开的位置,并且当它读取第一个++后自然期待变量;所以总之,编译器试图使用+x作为变量,这是无效的。

两者都可能有效使用其他编译器。这取决于语义。