2011-08-16 14 views
6

據稱面試問題和答案here對於不能編譯的C代碼,此解釋是否準確?

下面的代碼會編譯(在C中)嗎?

#define X 8; 
int main(void) 
{ 
    ++X; // will this line compile? 
}` 

我在C中沒有專家,但我知道一些C++,心想:當然不是,你不能遞增8號,這是一個右值。當然,預處理器在嘗試編譯之前用8代替X,並且當它試圖編譯時,它會因爲這個原因而失敗。話又說回來,我是一個讀書的面試問題網站這樣轉念一想,誰知道......

這裏給出的解釋:

「嚴格地說,前綴的操作數(或後綴)的增量操作者必須是一個不可修改的左值現在我們知道左值是什麼,我們必須問自己X是一個左值X是一個宏,這意味着它不能識別內存中的某個地方 - 宏使用簡單的文本替換預處理程序,因爲宏不存在於內存區域中,所以它們不是左值,這意味着X不能用作前綴增量運算符的操作數,因此,上面顯示的代碼將不會被編譯。

這個解釋是否像我認爲的那樣單調?

您可以在上面找到多少錯誤?我想,也許應該是面試的問題...

而這僅僅是有趣:

「直覺上,你也許可以說,上面的代碼不會編譯 - 不知道到底爲什麼然而,在面試的情況下,你應該提供一些如上所述的推理,簡單的是或否的答案在採訪中不會削減。

+5

不,它不會編譯,因爲它應該是'#define X 8',沒有';' –

+1

聽起來非常...學術... :) – Torp

+1

那麼,它也是一個錯誤(在C89中,在任何正常的警告集和程序員指導下)不會返回0;'或'main'末尾的其他數字...... –

回答

5

這個解釋是不是我認爲是錯的?

是的。

「嚴格地說,前綴的操作數(或後綴)遞增運算符必須是一個非修改的左值...

什麼不可修改的左值是一樣的東西const int n; - 你可以利用它的地址(通過&),但你不能分配給它(通過=+=,或++)。你不能增加東西是不可修改的。

引述標準(6.5.3.1條第1款):

預定義增量或減量運算符的操作數應具有限定的實數或指針類型,並應爲可修改的左值。

咳咳。

X是一個宏,這意味着它不識別內存中的某個位置 - 宏通過預處理器使用簡單的文本替換。

這是假的。宏不存在於C語言*中。他們是預處理器,它沒有左值,右值,表達式或內存的概念的一部分。 這種特殊的宏擴展爲整型常量,這是一個右值,但宏自己什麼都沒有做任何以上的。對於宏是一個左值的反見Steve Jessop's answer

正確的答案是,聲明擴展到++8,由於8是它不能被用來作爲參數傳遞給++右值(以兩種形式),所以它不會編譯。此外,取決於您是否打算將此代碼編譯爲C89或C99,如果沒有明確的return值則留下main可能會導致未定義的行爲。如果這將被接受的答案,我想我應該澄清一點:預處理器是C編程語言的一部分。它是在C標準中指定的,編譯器必須實現預處理才能成爲C編譯器。然而,C語言(即語法,語義,庫等)不與預處理器交互 - 一旦你開始處理左值和右值的階段,預處理器就已經存在很久了,所有宏都完全展開。因爲它們不是「語言」的一部分,所以宏自身在語法中沒有任何地方。關於在這裏使用術語「語言」是否具有誤導性,我有一些爭論(在史蒂夫傑索普的回答中),我同意他的看法,我只是找不到更好的詞來代替。

2

它不會編譯完全相同的原因(!):

8 = 8+1; 

將無法​​編譯。

你不能修改(這裏增加)一個常量。

10

給出的解釋是不正確的:

X是一個宏觀的,這意味着它不會在內存 確定一個地方 - 宏通過預處理用簡單的文本替換。

正因爲宏只是簡單的文本替換,他們可以擴大到左值,或爲此事別的。例如:

int x; 
#define X x 

int main() { 
    ++X; 
} 

沒問題。確實,宏本身在內存中沒有位置,但這與++X;是否格式完全無關,因爲++X;並不意味着「增加宏X」,這意味着「擴展宏X然後粘貼前面的++,背面的;,並對結果執行語法和語義分析「。

對「宏」的解釋是什麼,應該說大約是整數常量8不是一個左值,這是重要的。

隨着這種變化,對此的解釋是OK [編輯 - 克里斯在評論中指出,它仍然不能確定,它寫道:「前綴的操作數(或後綴)遞增運算符必須是一個不可修改左值「:應該讀爲」可修改「]

+1

+1宏不是C語言本身的一部分,與左值,右值,表達式和內存完全無關。這只是與宏觀相關的擴展。 (儘管'++'的參數必須是不可修改的左值也是錯誤的。) –

+1

我不確定說宏是不是「C語言本身」的一部分是有幫助的。它們不是可選的,它們是標準的一部分。但是如果你想把標準分成「語言」與「庫」或「預處理器」,例如「sizeof」是「語言的一部分」,而「INT_MIN」不是「語言的一部分」,那麼你當然可以在預處理程序,「編譯器本身」,標準頭文件,鏈接程序和可能的其他組件之間進行清晰的劃分,因爲翻譯的各個階段在標準中是明顯分開的。 –

+0

而且,呃,我錯過了「不可修改」的錯字。 –

2

該解釋僅對代碼無法編譯是正確的,但它在所有其他方面都是非常錯誤的。

它完全忽略的事實,編譯器將不會看到X,它會看到++8;;,所以關於運營商是否可以應用到X整個咆哮是沒有意義的。回答「不」比給出這樣的解釋要好得多。

0

它不會編譯,因爲前綴運算符需要位置值。 8是一個常數,它失敗了。您可以在這裏閱讀更多有關L值的信息:L-Value and R-Value Expressions