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

时间:2014-03-01 01:23:20

标签: c macros concatenation c-preprocessor conditional-compilation

我需要帮助宏!

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

#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。

知道怎么做吗?

感谢。

2 个答案:

答案 0 :(得分:1)

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

想象一下,您有一个名为m.h的头文件,其中包含以下内容:

#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 "m.h"

    #define ARG1 nachos
    #define ARG2 wednesday
    #include "m.h"
};

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

答案 1 :(得分:1)

你可以使用像Order-PP这样的高级宏库来做到这一点,虽然它的缺点是包含大量内容,可能会缩短编译时间,并且可疑的可移植性*。

执行您所要求的功能可能看起来像这样:

#include <order/interpreter.h>

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

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


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