C预处理器宏 – 基于参数连接的条件

我需要有关宏的帮助!

假设我已经定义了以下常量

#define foo_tacos_tuesday 1 #define foo_tacos 1 #define foo_nachos_wednesday 2 #define foo_nachos 3 

我想编写一个执行以下操作的宏

 #define MyFancyMacro( arg1, arg2 ) \ #if ( foo_ ## arg1 ## _ ## arg2 != foo_ ## arg1 ) \ foo_ ## arg1 ## _ ## arg2, foo_ ## arg1, 

所以我可以设置一个只映射不匹配值的映射表:

 static const int mappingTable[] = { MyFancyMacro(tacos, tuesday) MyFancyMacro(nachos, wednesday) }; 

最后,mappingTable的长度应为两个整数,包含2和3。

知道怎么做吗?

谢谢。

您无法将C预处理器宏扩展为预处理器语句。 但是,您可以使用文件包含来实现解决方法。

想象一下,你有一个名为mh的头文件,其中包含以下内容:

 #ifndef MY_FANCY_HEADER #define XFOO2(arg1, arg2) foo_ ## arg1 ## _ ## arg2 #define FOO2(arg1, arg2) XFOO2(arg1, arg2) #define XFOO(arg1) foo_ ## arg1 #define FOO(arg1) XFOO(arg1) #endif #define FOO_ARG1_ARG2 FOO2(ARG1, ARG2) #define FOO_ARG1 FOO(ARG1) #if FOO_ARG1_ARG2 != FOO_ARG1 FOO_ARG1_ARG2, FOO_ARG1, #endif #undef ARG1 #undef ARG2 #undef FOO_ARG1_ARG2 #undef FOO_ARG1 

然后,在源文件中,您可以执行以下操作:

 static const int mappingTable[] = { #define ARG1 tacos #define ARG2 tuesday #include "mh" #define ARG1 nachos #define ARG2 wednesday #include "mh" }; 

我承认它并不理想,但由于你无法将宏扩展为预处理器语句,我相信这是使用标准C预处理器实现它的唯一方法。

您可以使用像Order-PP这样的高级宏库来实现这一点,尽管其缺点是包含大量内容,可能会导致编译时间变慢,以及可疑的可移植性*。

做你要求的function可能看起来像这样:

 #include  // defining functions is a bit long-winded #define ORDER_PP_DEF_8fancy ORDER_PP_FN( \ 8fn(8L, 8R, \ 8if( 8equal(8L, 8R), \ 8print(8space), \ 8print(8L 8comma 8R 8comma) ) ) ) // testing this ORDER_PP ( // (execute Order code) 8fancy(1, 1) //should do nothing ) ORDER_PP ( 8fancy(2, 3) //should show 2,3, ) // wrap up in a conventional C macro #define MyFancyMacro(arg1, arg2) ORDER_PP( \ 8fancy( foo_ ## arg1 ## _ ## arg2, foo_ ## arg1 ) \ ) // test the full version #define foo_tacos_tuesday 1 #define foo_tacos 1 #define foo_nachos_wednesday 2 #define foo_nachos 3 static const int mappingTable[] = { MyFancyMacro(tacos, tuesday) //nothing MyFancyMacro(nachos, wednesday) //2,3, }; 

这是非常脆弱的 – 它只适用于整数,并且如果你试图比较其他东西,将会产生难以理解的错误信息。 即使这需要幕后的大量宏观魔法来启用类似==东西(它基本上有非常多的预设宏,例如EQUAL_1_1返回1而EQUAL_1_0返回0)。 Order语言的限制也意味着您需要对大于99的整数使用奇怪的格式。

if它本身非常容易定义为一个宏,并且只能用四个预处理器定义来完成 – 它是整数比较,它生成一个复杂部分的布尔值,因为你必须完全重新实现算术本身,只使用令牌替换。)

*订单符合标准,大多数编译器都不符合标准。


我还提醒我不要设计任何带有返回逗号的宏 – 这很可能会让其他人(甚至是你,当你忘记时)混淆,因为“语法”会停止与“语法输出”匹配。 事实上,鉴于此问题看起来像构建一个数组然后过滤掉值,为什么不在程序初始化期间在运行时实现呢?