在另一个宏中展开 X 宏

Expand X macro inside another macro

我有一个使用 fprintf() 打印输出的函数,它对格式字符串和参数都使用了一个宏。由于有多个地方打印此信息,这允许在仅更改一个地方的同时扩展打印。

我想使用相同的数据生成不同的打印件,但我希望它们使用 X-macro 自动扩展在一起,但我无法编译。我不希望每次添加要打印的内容时都需要编辑打印件,或者将每张打印件包装成丑陋的 #defines.

此程序尝试执行我想要的操作,但未编译:

#include <stdio.h>

#define X(_a, _b, _c) \
    _a,

#define TABLE \
    X("abc", "123", "ddd") \
    X("def", "456", "aaa") \
    X("ghi", "789", "ddd") \
    
#define STUFF \
    TABLE

#undef X
    
int main()
{
    printf(" %s %s %s\n", STUFF);

    return 0;
}

(我的想法是 STUFF 打印一个东西,在另一个地方我会用 X 宏的不同列做一个 STUFF2,称为 TABLE)

我收到以下错误:

main.c: In function ‘main’:

main.c:7:5: warning: implicit declaration of function ‘X’ [-Wimplicit-function-declaration]

X("abc", "123", "ddd") \

^

main.c:12:5: note: in expansion of macro ‘TABLE’

TABLE

^~~~~

main.c:18:27: note: in expansion of macro ‘STUFF’

printf(" %s %s %s\n", STUFF);

                      ^~~~~

main.c:8:5: error: expected ‘)’ before ‘X’

X("def", "456", "aaa") \

^

在扩展 STUFF 之前取消定义 X 会导致……好吧 X 未定义。

要使 X 宏正常工作,您必须在 在某些非宏代码中使用它之后 取消定义(以便它可以展开)

修复后,需要在列表中移动逗号,否则最后一个逗号将触发语法错误 (error: expected ‘)’ before ‘X’)。 TABLE

的最后一个反斜杠也一样
#include <stdio.h>

#define X(_a, _b, _c) \
    _a

#define TABLE \
    X("abc", "123", "ddd"), \
    X("def", "456", "aaa"), \
    X("ghi", "789", "ddd")

#define STUFF \
    TABLE
int main()
{
    printf(" %s %s %s\n", STUFF);

#undef X


    return 0;
}

这会编译、执行并打印 abc def ghi

main.c:7:5: warning: implicit declaration of function ‘X’ [-Wimplicit-function-declaration]

嗯,是的。在第18行,出现宏STUFF的地方,首先展开为

TABLE

,那就是重新扫描。 TABLE 被定义为宏,它也被扩展,导致

X("abc", "123", "ddd") X("def", "456", "aaa") X("ghi", "789", "ddd")

,然后 那个 被重新扫描。但是 X 不是 定义为宏(或其他任何东西),因为您之前 undefined 它。剩下的代码类似于对未知函数的三次调用,中间没有任何类型的运算符或分隔符。无效。

你的 X 宏必须在它展开的地方适当地定义。它根本不需要在它出现在另一个宏的扩展文本中的地方定义。你好像有点落后了。


正如评论中所讨论的那样,objective 能够定义单独的宏,例如 STUFFSTUFF2TABLE 扩展为不同的一致结果从彼此。这与通过操纵 X.

的定义导致 STUFF 按需要扩展相反

这可以通过更改 TABLE 的定义来实现,使其成为一个以另一个宏名称作为参数的类函数宏:

#define TABLE(m) \
    m("abc", "123", "ddd") \
    m("def", "456", "aaa") \
    m("ghi", "789", "ddd")

STUFFSTUFF2 然后可以通过选择要传递给哪个宏名称来控制扩展 TABLE():

#define X(_a, _b, _c) _a
#define Y(_a, _b, _c) _b
#define STUFF TABLE(X)
#define STUFF2 TABLE(Y)