【问题标题】:Can you feed a macro to another macro as an argument, without the initial macro being expanded?您可以将一个宏作为参数提供给另一个宏,而不扩展初始宏吗?
【发布时间】:2019-09-10 11:39:24
【问题描述】:

背景:我无法在此处发布的代码最终将在微控制器上运行,而宏只是提供了一种通过单个宏定义机制创建多个引脚定义功能的方法。我使用 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),由错误日志确认:

错误:“foo3”未在此范围内声明

所以要求是:

  1. 我需要将 BAR 传递给 MACRO1,它需要传递给 MACRO2 而不被扩展
  2. 单词 BAR 必须保持原样,我知道我可以使用 ## 来防止它扩展,但是我需要向 BAR 添加一个字符,并且函数调用将不再起作用。

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

【问题讨论】:

  • 我不是 100%,但这听起来不像是 this one 的骗子吗?
  • 注意你的语言不是C。
  • @500-InternalServerError,这个问题确实看起来是一样的,但一个答案实际上并没有回答那里提出的问题......或这里。

标签: c++ macros preprocessor


【解决方案1】:

但是这段代码会抛出一个错误,因为当 MACRO1(BAR) 得到 用 MACRO2(BAR) 替换, (BAR) 然后扩展为 3,并且 MACRO2(3) 导致 foo3(3)

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

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

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

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

#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;
}

这扩展为与另一个相同的东西。

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

【讨论】:

    【解决方案2】:

    实现这一点的一种方法是稍微改变 BAR 的定义。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-07-06
      • 1970-01-01
      • 2020-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多