2013-07-11 110 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作爲變量,這是無效的。

兩者都可能有效使用其他編譯器。這取決於語義。