2013-06-28 37 views
0

我正在嘗試爲其宏擴展測試gcc預處理器。GCC如何在宏中引用過程?

我寫下面的代碼:(只是用於測試)

#include <stdio.h> 

#define QUOTE " 
#define TMPL hello 

int main(){ 
    printf(QUOTE TMPL QUOTE); 
    return 0; 
} 

編譯結果是:

$ gcc main.c -o main 
main.c:3:15: warning: missing terminating " character 
main.c: In function ‘main’: 
main.c:7: error: missing terminating " character 
main.c:7: error: missing terminating " character 
main.c:7: error: ‘hello’ undeclared (first use in this function) 
main.c:7: error: (Each undeclared identifier is reported only once 
main.c:7: error: for each function it appears in.) 
main.c:7: warning: format not a string literal and no format arguments 
main.c:7: warning: format not a string literal and no format arguments 
$ 

然後我嘗試看看預處理的結果

$ gcc -E main.c -o tmp.c 
main.c:3:15: warning: missing terminating " character 
$ 

雖然發出警告,但它以某種方式在中產生正確的預處理代碼10

int main(){ 
printf(" hello "); 
return 0; 
} 

我編譯tmp.chello被正確打印。

我想知道爲什麼gcc -E可以產生正確的代碼,而使用gcc直接編譯失敗。 gcc預處理器的兩種方法有什麼區別?

$ gcc --version 
i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00) 
+0

預處理器宏應擴展爲一系列詞法分析令牌。所以你不能有像'#define QUOTE'這樣的宏';順便說一下,你的GCC版本很舊,現在的版本是4.8 –

+1

你想谷歌「c預處理器字符串」 – ugoren

回答

2

正如我所評論的,預處理器宏應擴展爲一系列詞法分析符號。使用GCC源代碼,libcpp(負責預處理和標記)產生了一個令牌流(不是普通的字符串)。最近GCC 4.8,當爲gcc -Wall endyul.c -o endyl上你的榜樣運行,給人非常有幫助診斷:

endyul.c:3:15: warning: missing terminating " character [enabled by default] 
#define QUOTE " 
      ^
endyul.c: In function 'main': 
endyul.c:7:5: error: missing terminating " character 
    printf(QUOTE TMPL QUOTE); 
    ^
endyul.c:7:5: error: missing terminating " character 
endyul.c:4:14: error: 'hello' undeclared (first use in this function) 
#define TMPL hello 
      ^
endyul.c:7:18: note: in expansion of macro 'TMPL' 
    printf(QUOTE TMPL QUOTE); 
       ^
endyul.c:4:14: note: each undeclared identifier is reported only once for each function it appears in 
#define TMPL hello 
      ^
endyul.c:7:18: note: in expansion of macro 'TMPL' 
    printf(QUOTE TMPL QUOTE); 
       ^

你的GCC 4.2已經很老了。你應該考慮升級它。

而且clang(3.3)也提供了一個很好的診斷:

clang -Wall endyul.c -o endyul 
endyul.c:3:15: warning: missing terminating '"' character [-Winvalid-pp-token] 
#define QUOTE " 
      ^
endyul.c:7:12: error: expected expression 
    printf(QUOTE TMPL QUOTE); 
      ^
endyul.c:3:15: note: expanded from macro 'QUOTE' 
1 warning and 1 error generated. 

再次閱讀CPP manual of GCC,尤其是在StringificationConcatenation的章節。

+0

thx,但是爲什麼'gcc -E'生成正確的代碼? – endyul

+0

因爲'gcc -E'不會產生代碼,而是恰好看起來正確(但不是)的文本C預處理被定義爲產生一個令牌流(在上個世紀,舊編譯器之前C99標準有預處理程序生成文本;標準要求預處理應產生令牌,而不是純文本)。 –