有没有一种方法可以将宏名称作为参数传递给嵌套宏,而不会在扩展最外层的宏时扩展它们?

Posted

技术标签:

【中文标题】有没有一种方法可以将宏名称作为参数传递给嵌套宏,而不会在扩展最外层的宏时扩展它们?【英文标题】:Is there a way of passing macro names as arguments to nested macros without them being expanded when the outermost macro is expanded? 【发布时间】:2015-02-13 06:02:35 【问题描述】:

(抱歉,标题太长了,但我想不出一个更具体但足够清楚的标题)

我需要将(类对象)宏的名称传递给嵌套(类函数)宏,如以下(简单)示例:

#define ROOT_FUNC(INPUT) int v_ ## INPUT = INPUT
#define CALLER_FUNC(INPUT) ROOT_FUNC(INPUT)

#define INTA 1
#define INTB 2
#define INTC 3

现在,如果我在代码中写入ROOT_FUNC(INTA);,我会得到一个名为v_INTA 的整数变量,其值为1。如果我在代码中定义一个变量int INTD = 4;,然后编写CALLER_FUNC(INTD);,我最终会得到一个名为v_INTD 的整数变量,其值为4

但是如果我写CALLER_FUNC(INTA);,我会得到一个名为v_1 的整数变量,其值为1,因为INTACALLER_FUNC 扩展时扩展为1,在ROOT_FUNC 之前被扩展(即ROOT_FUNC(1) 被扩展)。

如果我将第 2 行更改为:#define CALLER_FUNC(INPUT) ROOT_FUNC(#INPUT)(即对INPUT 进行字符串化),则会发生编译器错误,因为它被要求定义一个名为v_"1"(无效名称)的整数变量并为其赋值@ 987654340@(非整数值)。

我知道预处理器相当原始,但是有什么方法可以实现我所追求的吗?

(第二次编辑以进一步澄清,我希望 CALLER_FUNC(INTA); 首先扩展为 ROOT_FUNC(INTA);,然后扩展为 int v_INTA = 1; - 即我希望 INTAROOT_FUNC 内部扩展,而不是在其外部。我是原则上寻找答案,而不仅仅是改变CALLER_FUNC以产生结果int v_INTA = 1;的任何方式,这将是微不足道的)。


附: 如果您想知道,我最初有一个涉及信号处理的用例(例如,将 SIGINT 之类的宏名称作为嵌套宏的输入),但通过简化我的结构并放弃嵌套宏来解决这些限制;因此这个问题纯属学术性的。

【问题讨论】:

我仍然不清楚你想要什么。请举例说明预期输出是什么。 MASTER 是什么?你的意思是ROOT_FUNC @remyabel 所需的输出将是:CALLER_FUNC(INTA); 扩展为 ROOT_FUNC(INTA);,然后扩展为 int v_INTA = 1;(具体示例只是一个随机且微不足道的示例)。目前它扩展到ROOT_FUNC(1);,然后扩展到int v_1 = 1;(即INTA在传递给ROOT_FUNC()之前被扩展,而我希望它在之后发生)。 @T.C.我确实——已经改变了。 我认为这是不可能的。如果我正确阅读规范,参数在被替换到替换列表之前会被宏扩展,除非它们是 ### 的操作数,但在这些情况下你没有办法拿回论据。 【参考方案1】:

如果你可以扩展第一个宏来接受两个参数,你可以让它像这样工作:

#define FUNC(intname, intv) int v##intname = intv
#define CALL_FUNC(intv) FUNC(_##intv, intv)

#define INT1 1
#define INT2 2

int main(void)

  int INTD = 4;

  CALL_FUNC(INT1);
  CALL_FUNC(INT2);
  CALL_FUNC(INTD);

输出(来自 GCC)看起来像这样:

int main(void)

  int INTD = 4;

  int v_INT1 = 1;
  int v_INT2 = 2;
  int v_INTD = INTD; // not sure if you want the value of INTD here - I guess it doesn't matter?

我猜你想要的是什么——如果我没看错你的问题?

标记粘贴可防止预处理器将其扩展并简单地生成一个新标记,该标记传递给第二个宏(然后将其简单地粘贴在一起以形成变量),值(已扩展)被传递为第二个论点..


EDIT1:阅读更多你所追求的东西,我猜上面的技巧不是你真正想要的......嗯......

【讨论】:

这实际上是一个非常好的 hack——事实上,这在我原来的(现在被放弃的)用例中是有效的。这当然只适用于内部函数想要粘贴宏的情况的子集,但只有三种可能的情况:内部函数可以粘贴、扩展或字符串化宏,而后两种情况无关紧要。宏被扩展/字符串化的链,结果总是相同的。因此,我认为我们现在有一个完整的模型。唯一的缺点是多个调用函数可能必须包含相同的粘贴,从而降低了宏效率。

以上是关于有没有一种方法可以将宏名称作为参数传递给嵌套宏,而不会在扩展最外层的宏时扩展它们?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在不重复变量名的情况下将命名参数传递给格式化宏?

嵌套表单 - 我无法将所有属性参数传递给我的强参数

C语言带参数的宏定义:定义宏名时可以不写出参数???

为什么我们将请求作为参数传递给django的render方法?

我可以将数组和变量作为参数传递给 C# 中的方法吗? [复制]

宏定义