【问题标题】:Difference in preprocessor output预处理器输出的差异
【发布时间】:2018-05-24 16:35:52
【问题描述】:

我试图检查一些具有 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;
}

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

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

编辑:我本身并不想实现任何功能,这只是一个练习(徒劳?)以了解预处理器。

【问题讨论】:

  • 您期望预处理器提供一些它根本无法做到的事情。它不会递归替换,它只有一次。顺便说一句,你想做的 99% 都可以用纯 c++ 实现,c++ 永远不需要复杂的宏
  • 因为一个宏不能用来定义另一个宏,你为什么要关心?
  • @pm100 我想你还没有理解我的问题。我在问为什么输出有差异。我不希望它“做事”,我只是在问它为什么会这样?
  • @NeilButterworth 好的。您能否指导我参考其中提到的标准或参考?我找不到它。这也不是另一个“宏中的宏”,对吧?这只是同一行中的另一个指令。
  • 第一个是类对象宏,第二个是类函数宏。宏函数会作用于宏函数参数,这是#if试图做的,但是if不是宏参数,所以失败了。

标签: c++ preprocessor


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 2011-04-14
    • 2011-08-21
    • 1970-01-01
    • 2021-02-18
    • 2021-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多