2016-05-15 33 views
4

我所做的代碼片斷簡單解釋C預處理器如何實際工作?

// Example 1 

#define sum2(a, b) (a + b) 
#define sum3(a, b, c) (sum2(a, sum2(b, c))) 

sum3(1, 2, 3) // will be expanded to ((1 + (2 + 3))) 


// Example 2 

#define score student_exam_score 
#define print_score(student_exam_score) printf("%d\n", score) 
#undef score 

print_score(80); // will be expanded to printf("%d\n", score); 
       // but not printf("%d\n", 80); that I expect 

第一個是直觀的,而種編碼存在在幾個地方如查找最大或最小數。但是,我想用這種技術使我的代碼變得簡潔易讀,所以我用一個更短且更有意義的名稱替換了宏中的一些單詞。

AFAIK,C預處理器每個編譯單元只運行一次,只執行字符串替換,但爲什麼print_score不能擴展爲printf("%d\n", 80);

這是在更換過程我想:

#define score student_exam_score 
#define print_score(student_exam_score) printf("%d\n", score) 
#undef score 

print_score(80); 

// --> 

#define score student_exam_score // runs this first 
#define print_score(student_exam_score) printf("%d\n", student_exam_score) // changed 
#undef score 

print_score(80); 

// --> 

#define score student_exam_score 
#define print_score(student_exam_score) printf("%d\n", student_exam_score) // then this 
#undef score 

printf("%d\n", 80); // changed 
+0

print_score(80); => printf(「%d \ n」,score)=> printf(「%d \ n」,student_exam_score),所以這就是問題所在。 – BlackMamba

+0

@BlackMamba第一次將'print_score(student_exam_score)printf(「%d \ n」,score)'替換爲'print_score(student_exam_score)printf(「%d \ n」,student_exam_score)'嗎? –

+1

「* C預處理器每個編譯單元只運行一次*」和「*爲什麼'print_score'不能擴展爲'printf(」%d \ n「,80);'?*」後者正是因爲前者。 – alk

回答

3

這是一個順序的問題。首先定義宏,並且score在它被使用之前是未定義的。然後,當print_score被展開時,它將首先替換student_exam_score的所有實例,其中沒有任何實例。然後它重新掃描結果,尋找更多的宏來擴展,但是沒有,因爲score未定義並且不再可用。

即使你移動#undef score下來參考下面print_score,它仍然是行不通的,因爲參數替換隻會發生一次(score將擴大,但student_exam_score不會)。

請注意,score未被替換爲print_score正文中的定義。只有宏被實例化時纔會發生替換,這就是爲什麼#undef score結果爲score宏無論如何都沒有任何影響。

這些例子會使它更清晰。首先,考慮以下因素:

#define foo bar 
#define baz(bar) (foo) 
baz(123) 

此如下擴展:

baz(123) 
-> (foo) 
-> (bar) 

擴張到此爲止。在擴展foo之前完成參數替換,並且不再發生。

現在考慮以下幾點:

#define foo bar 
#define baz(bar) (foo) 
#undef foo 
baz(123) 

此如下擴展:這裏

baz(123) 
-> (foo) 

擴張停止,因爲foo不再定義。其較早的定義對baz的定義沒有影響,因爲宏定義時不會發生宏替換。只有在擴展時纔會發生。

+0

爲什麼'score'未定義?我不確定預處理是否存在未定義的問題。 –

+0

這是一個測序問題。 '#undef score'在它被使用之前不定義'score'。請參閱我剛剛添加的答案中的最後一段。 –

+0

'#undef'只是爲了不影響下面的代碼。 –