预处理器输出的差异

Difference in preprocessor output

本文关键字:输出 处理器 预处理      更新时间:2023-10-16

我试图检查一些具有 2 个预处理器指令的单行宏。

#define REPLACE  { 
#if EXT == 42 
#warning "Got 42" 
#endif 
}
int main(void){
REPLACE;
return 0;
}

预处理器解析此精细结果:

$g++ -E includetest.cpp
# 1 "includetest.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "includetest.cpp"
int main(void){
{ #if EXT == 42 #warning "Got 42" #endif };
return 0;
}

这当然是非法代码,因为只发生宏替换,并且 ifdef 外观宏不会再次处理,即使它看起来像一个宏。

现在,如果我稍微更改宏以看起来像

#define REPLACE(a)  { a + 2 ; 
#if EXT == 42 
#warning "Got 42" 
#endif 
}
int main(void){
REPLACE(0);
return 0;
}

这会产生以下预处理器错误:

$g++ -E includetest.cpp
# 1 "includetest.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "includetest.cpp"
includetest.cpp:1:18: error: '#' is not followed by a macro parameter
#define REPLACE(a)  { a + 2 ; 
^
int main(void){
REPLACE(0);
return 0;
}

为什么会出现此错误?当然,这不会编译,但我想知道为什么在预处理器的解析错误中添加参数?

人们会说"你不能在另一个指令中嵌套另一个指令",但在第一种情况下,它们也是嵌套的,为什么预处理器错误不出来呢?还是该责任委托给编译器?

编辑:我并不是要实现任何功能本身,这只是理解预处理器的一种练习(徒劳的?(。

只有在函数宏中,#才具有特殊含义([cpp.stringize]p1(。该标准说#后面需要跟一个函数参数,这在第二种情况下不会发生(ifwarningendif不是参数(。

您的第一种情况是有效的(您实际上可以在对象宏的替换列表中包含指令(,正是因为#没有任何特殊含义。