预处理器输出的差异
Difference in preprocessor output
我试图检查一些具有 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)。该标准表示 #
需要后跟一个函数参数,这在您的第二种情况下不会发生(if
、warning
和 endif
不是参数)。
您的第一种情况是有效的(您实际上可以在对象宏的替换列表中包含指令)正是因为 #
没有任何特殊含义。
我试图检查一些具有 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)。该标准表示 #
需要后跟一个函数参数,这在您的第二种情况下不会发生(if
、warning
和 endif
不是参数)。
您的第一种情况是有效的(您实际上可以在对象宏的替换列表中包含指令)正是因为 #
没有任何特殊含义。