14

有没有办法编写一个 C 预处理器宏,根据它收到的参数扩展到不同的东西?

#define foo() ???

/* 1 */
foo(name)

/* 2 */
foo(_)

期望的结果:

/* 1 */
int name;

/* 2 */
/*ignore*/

是的,我知道宏是邪恶的。我问这个主要是出于好奇。

4

3 回答 3

16

要扩展 Gavin Smith 的答案,您实际上可以检查宏扩展中的条件:

#define FOO_name 1
#define FOO__ 0

#define CONC(a,b) a##_##b

#define IF(c, t, e) CONC(IF, c)(t, e)
#define IF_0(t, e) e
#define IF_1(t, e) t

#define FOO(x) IF(CONC(FOO,x), int x;, )

FOO(name) // -> int name;
FOO(_)    // -> /*nothing*/

如果您喜欢冒险,您可以IF使用辅助宏轻松扩展以允许逗号、抑制宏扩展等。

如上所述,但这确实需要您提前知道所有所需的名称。

于 2013-09-26T00:54:52.757 回答
8

也许尝试一些多阶段的宏扩展?这是Boost 预处理器/控制/if 库使用的策略。

#define FOO_NAME 1
#define FOO__ 2

#define CONC(a,b) a##_##b
#define FOO(x) CONC(FOO,x)

我认为没有任何方法可以检查 C 宏扩展中的条件。

我能想到的最好的办法是使用#字符串化运算符将宏参数转换为字符串文字,然后使用运行时函数进行检查。(但是,这不适用于您要输出变量声明的情况。)

例如,以下打印“011”:

#define FOO(x) (strcmp("NAME", #x) ? 1 : 0)

main()
{
    printf("%d", FOO(NAME));
    printf("%d", FOO(1));
    printf("%d", FOO(2));
}

编译器可能会strcmp在编译时优化比较,因此它不会比真正的预处理器条件可用时效率低。但是,制作FOO一个正常的功能会更清晰,并且可能同样有效。

于 2013-09-25T17:19:20.233 回答
1

使用此处描述的技巧,可以在编译时执行您想要的操作。

您可以使用EQUAL文档末尾定义的宏,然后执行以下操作:

#define COMPARE__(x) x
#define OPTION_0(x) int x;
#define OPTION_1(x) /* nothing */
#define foo(x) CAT(OPTION_, EQUAL(_, x))(x)

foo(name1) // int name1;
foo(_)     // /* nothing */
foo(name2) // int name2;
于 2018-09-20T20:46:48.280 回答