在另一个宏内展开X宏

时间:2019-11-28 20:06:56

标签: c macros x-macros

我有一个使用fprintf()打印输出的函数,并且它同时使用宏作为格式字符串和参数。由于有多个地方可以打印此信息,因此可以在只更改一个地方的同时扩展打印范围。

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

该程序尝试执行我想要的操作,但无法编译:

#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宏的另一列TABLE创建STUFF2)

我收到以下错误:

  

main.c:在“ main”函数中:

     

main.c:7:5:警告:函数“ X”的隐式声明[-Wimplicit-function-declaration]

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

^
     

main.c:12:5:注意:扩展宏“ TABLE”

TABLE

^~~~~
     

main.c:18:27:注意:扩展宏“ STUFF”

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

                      ^~~~~
     

main.c:8:5:错误:预期在“ X”之前的“)”

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

^

2 个答案:

答案 0 :(得分:1)

X扩展前未定义STUFF会导致…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

答案 1 :(得分:1)

  
    

main.c:7:5:警告:函数“ X”的隐式声明[-Wimplicit-function-declaration]

  

是的,是的。在第18行显示宏STUFF的位置,首先将其扩展为

TABLE

,然后重新扫描。 TABLE被定义为宏,它也被扩展,导致

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

,然后那个被重新扫描。但是此时X还没有被定义为宏(或其他任何东西),因为您先前undef已将其插入。剩下的代码类似于对未知函数的三个调用,而没有任何类型的运算符或分隔符。无效。

您的X宏必须在扩展位置适当定义。完全不需要在另一个宏的扩展文本中出现的位置对其进行定义。您似乎倒退了。


如评论中所述,目标是能够定义单独的宏,例如将STUFF扩展为彼此不同的一致结果的STUFF2TABLE。这与通过操纵STUFF的定义使X扩展所需的内容相反。

这可以通过更改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)