我正在尝试测试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
$
虽然发出警告,但它会以某种方式在tmp.c
int main(){
printf(" hello ");
return 0;
}
我编译tmp.c
,hello
已正确打印。
我想知道为什么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 :(得分: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,特别是Stringification和Concatenation上的章节。