是否可以在C宏中放置预处理器条件?

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

#define foo() ??? /* 1 */ foo(name) /* 2 */ foo(_) 

期望的结果:

 /* 1 */ int name; /* 2 */ /*ignore*/ 

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

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

 #define FOO_NAME 1 #define FOO__ 2 #define CONC(a,b) a##_##b #define FOO(x) CONC(FOO,x) 

我认为没有办法检查C宏扩展中的条件。

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

例如,以下打印“011”:

 #define FOO(x) (strcmp("NAME", #x) ? 1 : 0) main() { printf("%d", FOO(NAME)); printf("%d", FOO(1)); printf("%d", FOO(2)); } 

编译器可能会在编译时优化strcmp比较,因此它不会比真正的预处理器条件可用strcmp 。 然而,使FOO成为正常function将更加清晰,并且可能同样有效。

要扩展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以允许逗号,抑制宏扩展等辅助宏。

如上所述虽然这确实需要您事先知道所有所需的名称。

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

您可以使用文档末尾定义的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;