2014-05-14 62 views
1

我碰到一個更加一段代碼是更加混亂..宏不起作用

#include "stdio.h" 

#define f(a,b) a##b 

#define g(a) #a 

#define h(a) g(a) 

int main(void) 
{ 
    printf("%s\n",h(f(1,2))); 
    printf("%s\n",g(1)); 
    printf("%s\n",g(f(1,2))); 
    return 0; 
} 

輸出

12 

1 

f(1,2) 

我的假設是 1)第一f(1,2)被替換出來由12,因爲宏f(a,b) concantenates其論據 2)然後g(a)宏替換1一個字符串升人"1" 3)輸出應爲1

但是爲什麼g(f(1,2))沒有得到取代以12。 我相信我在這裏錯過了一些東西。 有人可以解釋我這個程序嗎?

+3

因爲g是在f之前求值的,它將'f(1,2)'轉換爲一個字符串文字。 –

+2

你說標題中的C(你不需要),但標記C++?這可能沒有什麼不同,但你應該保持一致。 – crashmstr

回答

2

宏替換從外面發生。(嚴格地說,預處理器需要運行,就好像在一個時間替換宏之一,從文件的開頭開始,每次更換後重新啓動。)

標準(C99§6.10.3.2/ 2)表示,

如果在替換列表,一個參數被立即由#預處理 令牌之前,二者由單個字符串文字預處理標記替換了 包含預處理令牌sequ的拼寫因爲相應的 參數。

#由於存在於用於宏g替換列表,參數f(1,2)被立即轉換爲字符串,並且結果是"f(1,2)"

在另一方面,在h(f(1,2)),因爲替換列表中不包含#,§6.10.3.1/ 1適用,

參數的函數宏調用之後一直確定, 參數替換髮生。在替換列表中的參數,除非由###預處理記號預處理記號或後跟一個##(見下文),是 通過包含在其中的所有的宏之後的相應參數代替前面 已經 擴大。

和參數f(1, 2)被宏膨脹,得到12,所以結果是g(12)然後變成"12"當該文件被「重新掃描」。

1

宏無法擴展爲預處理指令。從C99 6.10.3.4/3「重新掃描和再替換」:

所得完全宏取代預處理標記序列 不被處理作爲預處理指令,即使它酷似 一個,

來源:https://stackoverflow.com/a/2429368/2591612

但你可以撥打f(a,b)g就像你用h做的那樣。 f(a,b)被解釋爲一個字符串字面值爲@Red Alert的狀態。