c++ - 您可以将一个宏作为参数提供给另一个宏,而不扩展初始宏吗?

标签 c++ macros preprocessor

背景:我的代码(我无法在此处发布)最终将在微 Controller 上运行,并且宏仅提供一种通过 1 个宏定义机制创建多个引脚定义函数的方法。我使用 windows 和 gcc 来尝试这些。

我尝试尽可能地抽象问题。我使用 std 控制台函数是因为我可以方便地将其显示在控制台窗口中。因此,我还将文件另存为 .cpp 并在 Windows 上使用 g++ 进行编译。

假设我这样设置代码:

#define MACRO2(_x)  foo##_x(_x)
#define MACRO1(_x)  MACRO2(_x)
#define BAR         3   

void fooBAR(int num)
{
    std::cout << num << std::endl;
}

如果我运行以下代码(工作示例)

int main()
{
    MACRO2(BAR);
    return 0;
}

第一个 BAR 被插入到 ##_x 中,从而定义要调用的函数名称,然后 BAR 作为该函数的参数插入并扩展为其值,因此我们得到 fooBAR(3)。代码有效,没有错误。

现在,如果我尝试在两者之间添加一个宏(这是我由于无法深入的原因而面临的现实世界情况),我的代码如下所示:

int main()
{
    MACRO1(BAR);
    return 0;
}

但是此代码会引发错误,因为当 MACRO1(BAR) 被 MACRO2(BAR) 替换时,(BAR) 会扩展为 3,而 MACRO2(3) 会导致未定义的 foo3(3),错误日志确认:

error: 'foo3' was not declared in this scope

所以要求是:

  1. I need to pass BAR into MACRO1 and it needs to be passed to MACRO2 without being expanded
  2. The word BAR has to stay exactly as it is, I know I could use ## in order to prevent it from expanding, but then I would need to add a char to BAR and the function call wouldn't work anymore.

有可能以某种方式完成这件事吗?将一个宏作为参数传递给另一个宏,而不在此过程中扩展初始宏?

最佳答案

But this code throws an error, because when MACRO1(BAR) gets substituted with MACRO2(BAR), (BAR) then gets expanded into 3, and MACRO2(3) leads to foo3(3)

是的。这是为您的特定宏集指定的预处理器行为。

在识别出类函数宏的参数后,它们在被替换到宏的替换文本之前会被完全宏扩展,除非它们是 ## 的操作数# 预处理器运算符。评估这些运算符的任何外观,然后重新扫描生成的文本以及适当的任何后续文本,以扩展其他宏。

Is it possible to somehow get this done? Pass a macro to another macro as an argument, without the initial macro being expanded in the process?

仅当参数是 ### 运算符的操作数时。后者对您没有帮助,但前者提供了一种解决方法:您可以传递一个附加的空参数,以便您可以在不更改所需参数的情况下执行串联:

#define MACRO2(_x)        foo##_x(_x)
#define MACRO1(_x,dummy)  MACRO2(_x##dummy)
#define BAR               3   

int main()
{
    MACRO1(BAR,);
    return 0;
}

扩展为

int main()
{
    fooBAR(3);
    return 0;
}

如果你想避免额外的逗号,那么你可以通过设置 MACRO1 变量来实现:

#define MACRO2(_x)      foo##_x(_x)
#define MACRO1(_x,...)  MACRO2(_x##__VA_ARGS__)
#define BAR             3   

int main()
{
    MACRO1(BAR);
    return 0;
}

它扩展到与另一个相同的东西。

请注意,这两种方法都有可能通过向顶级宏提供不需要的额外参数值来引入错误。人们可能会认为大多数此类错误会在编译时被捕获,因为扩展会导致代码损坏,就像问题中的尝试一样。但很难排除这样的可能性:这种错误会巧合地扩大到碰巧有效但错误的事情。

关于c++ - 您可以将一个宏作为参数提供给另一个宏,而不扩展初始宏吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57870022/

相关文章:

vim - 如何停止运行 Vim 宏

python - 有谁知道 FMPP 的 Python 等价物?

c++ - 什么时候销毁异常对象(并且可以控制)?

c++ - 未安装 Gurobi 机器中的 Gurobi 可执行文件

python - Swig 错误 - 错误 : Syntax error in input(2)

c++ - 将指针取消引用作为 for 循环条件?

macros - `:expr` 后跟 `:tt` ,`expr` 片段不允许

c++ - 名称不同但参数相同的函数

c - 用于在 C 中创建关键字的预处理器指令

html - 防止 Prepos 处理某些 scss 文件?