【问题标题】:C Preprocessor Macros - conditionals based upon argument concatenationC 预处理器宏 - 基于参数连接的条件
【发布时间】:2014-04-02 06:21:05
【问题描述】:

我需要宏方面的帮助!

假设我定义了以下常量

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

知道怎么做吗?

谢谢。

【问题讨论】:

  • 答案都很无礼...重新考虑你的方法。您没有提供足够的上下文,但它确实看起来像经典的 XY problem。

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


【解决方案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 预处理器进行此操作的唯一方法。

【讨论】:

    【解决方案2】:

    您可以使用像 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 本身很容易定义为宏,只需四个预处理器定义即可完成 - 它是整数比较,它生成一个布尔值,这是复杂的部分,因为您必须完全重新实现 算术本身 只使用令牌替换。)

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


    我还告诫不要设计任何带有返回逗号的宏的东西 - 这很可能会混淆其他人(甚至是你,当你忘记时),因为“语法输入”不再与“语法输出”匹配。事实上,考虑到这个问题看起来就像构建一个数组然后过滤掉值,为什么不在程序初始化期间在运行时真正这样做呢?

    【讨论】:

      猜你喜欢
      • 2012-07-22
      • 2016-03-30
      • 1970-01-01
      • 2015-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-25
      • 2020-09-18
      相关资源
      最近更新 更多