是否可以在 C 宏中放置条件预处理器?
Posted
技术标签:
【中文标题】是否可以在 C 宏中放置条件预处理器?【英文标题】:Is it possible to put a preprocessor conditional inside a C macro? 【发布时间】:2013-09-25 17:02:31 【问题描述】:有没有办法编写一个 C 预处理器宏,根据它收到的参数扩展为不同的东西?
#define foo() ???
/* 1 */
foo(name)
/* 2 */
foo(_)
想要的结果:
/* 1 */
int name;
/* 2 */
/*ignore*/
是的,我知道宏是邪恶的。我问这个主要是出于好奇。
【问题讨论】:
宏太棒了。 您能否解释一下目的,或者举一个更好的例子?该参数必须在编译时固定,这意味着您也可以使用两个不同的宏名称。 @mbratch:在这种特殊情况下,我使用宏来定义一组变量,但有些变量是可选的,我想避免定义它们。由于组合爆炸,多个宏名称无法正常工作:对于两个变量名称,我需要为foo(a,b)
、foo(a,_)
、foo(_,b)
和 foo(_,_)
使用单独的宏。
那么你是在尝试实现一种重载形式。也许您应该研究可变参数宏。看到这个问题***.com/questions/3420459/…
@TheodorosChatzigiannakis:问题是我需要重载传递宏的值,而不是参数的数量。
【参考方案1】:
要扩展 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
以允许逗号、抑制宏扩展等。
如上所述,但这确实需要您提前知道所有所需的名称。
【讨论】:
【参考方案2】:也许尝试一些多阶段的宏扩展?这是Boost preprocessor/control/if library使用的策略。
#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
设为普通函数会更清晰,并且可能同样有效。
【讨论】:
有趣的把戏!但是有没有一种方法我不需要列举“1”案例的所有可能性?例如,如果它是_
,那么宏会产生 2,如果它的其他任何东西产生 1?
我用有限的解决方法更新了我的答案,该解决方法不适用于您的原始问题。
不幸的是,我不能在我的案例中使用运行时测试。我开始认为你的第一个解决方案是我能得到的最好的解决方案。
@hugomg 你想要的都是可能的,但是它需要很多肮脏的预处理技巧:github.com/pfultz2/Cloak/wiki/…我会添加一个答案【参考方案3】:
使用here 描述的技巧,可以在编译时做你想做的事。
您可以使用文档末尾定义的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;
【讨论】:
以上是关于是否可以在 C 宏中放置条件预处理器?的主要内容,如果未能解决你的问题,请参考以下文章