您可以将一个宏作为参数提供给另一个宏,而不扩展初始宏吗?
Can you feed a macro to another macro as an argument, without the initial macro being expanded?
背景:我的代码,我不能在这里post最终会运行在微控制器上,宏只是提供了一种方法来创建多个引脚定义功能,通过 1 个宏定义机制。我使用 windows 和 gcc 来试验这些。
我试图尽可能地抽象问题。我使用 std 控制台函数,因为我可以方便地在控制台中显示它 window。因此,我还将文件另存为 .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
所以要求是:
- I need to pass BAR into MACRO1 and it needs to be passed to MACRO2 without being expanded
- 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;
}
扩展为与另一个相同的东西。
请注意,这两种方法都可能通过向顶级宏提供不需要的额外参数值来引入错误。人们可能会认为大多数此类错误会在编译时被捕获,因为扩展会导致代码损坏,就像问题中的尝试一样。但是很难排除这样的错误会巧合地扩展到恰好有效但错误的事情的可能性。
完成此操作的一种方法是稍微更改 BAR 的定义。
#define MACRO2(_x) foo##_x(_x())
#define MACRO1(_x) MACRO2(_x)
#define BAR() 3
背景:我的代码,我不能在这里post最终会运行在微控制器上,宏只是提供了一种方法来创建多个引脚定义功能,通过 1 个宏定义机制。我使用 windows 和 gcc 来试验这些。
我试图尽可能地抽象问题。我使用 std 控制台函数,因为我可以方便地在控制台中显示它 window。因此,我还将文件另存为 .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
所以要求是:
- I need to pass BAR into MACRO1 and it needs to be passed to MACRO2 without being expanded
- 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;
}
扩展为与另一个相同的东西。
请注意,这两种方法都可能通过向顶级宏提供不需要的额外参数值来引入错误。人们可能会认为大多数此类错误会在编译时被捕获,因为扩展会导致代码损坏,就像问题中的尝试一样。但是很难排除这样的错误会巧合地扩展到恰好有效但错误的事情的可能性。
完成此操作的一种方法是稍微更改 BAR 的定义。
#define MACRO2(_x) foo##_x(_x())
#define MACRO1(_x) MACRO2(_x)
#define BAR() 3