【问题标题】:C Preprocessor to compute product specific include用于计算产品特定包括的 C 预处理器
【发布时间】:2017-01-20 14:38:17
【问题描述】:

我必须维护具有通用组件和产品特定组件的 C 代码。我想简化我的代码,以便我只有一个通用 product.h 文件,其结构类似于

#if (PRODUCT_ID == 1)
    #define PRODUCT_NAME Product1
#else
    #if (PRODUCT_ID == 2)
        #define PRODUCT_NAME Product2
    #else
        #error "Unsupported product id"
    #endif
#endif

然后,每当我有一个包含产品特定组件的标题 foo.h 时,我想使用这样的语法

#include "product.h"
#include PRODUCT_SPECIFIC_INCLUDE

PRODUCT_SPECIFIC_INCLUDE 应该从 __FILE__ 和 PRODUCT_NAME 宏派生而来,这样它可以转换为

#include "Product1/foo.h"

即产品特定头文件与通用文件具有相同的文件名,但位于产品特定文件夹中,其名称为PRODUCT_NAME宏的值。

似乎无论我尝试什么都有预处理器字符串化问题。我不可能是第一个想要这种结构的人。我错过了什么?

更新

这是我目前为PRODUCT_SPECIFIC_INCLUDE 提供的,但它不起作用

#define TOKENPASTE(x, y) x ## y
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)
#define PRODUCT_SPECIFIC_INCLUDE TOKENPASTE2(PRODUCT_SPECIFIC, __FILE__)

【问题讨论】:

  • 我不确定是否可以使用标准 C 预处理器。您可能不得不在构建环境中执行此操作。
  • 请出示与PRODUCT_SPECIFIC_INCLUDE相关的宏
  • 这是我目前拥有的 PRODUCT_SPECIFIC_INCLUDE 不起作用 #define TOKENPASTE(x, y) x ## y #define TOKENPASTE2(x, y) TOKENPASTE(x, y ) #define PRODUCT_SPECIFIC_INCLUDE TOKENPASTE2(PRODUCT_SPECIFIC, __FILE__)
  • 最好将其添加到问题正文中,因为它是重要的部分。

标签: macros c-preprocessor generic-programming stringification


【解决方案1】:

你可以这样做

#define STR2(F) #F
#define STR(F) STR2(F)
#define MAKE_PRODUCT_INCLUDE(FILE) STR(PRODUCT_SPECIFIC/FILE)

#include MAKE_PRODUCT_INCLUDE(foo.h)

但我不知道如何避免重复文件名。使用__FILE__ 给出了一个字符串,并且我不知道在预处理器中连接字符串(并列字符串连接的事实是解析器功能,## 不适用于那个“foo”“bar”是不是有效令牌的拼写)。

【讨论】:

    【解决方案2】:

    第一个代码可以简化为:

    #if (PRODUCT_ID == 1)
        #define PRODUCT_NAME Product1
    #elif (PRODUCT_ID == 2)
        #define PRODUCT_NAME Product2
    #else
        #error "Unsupported product id"
    #endif
    

    其次,您正在尝试获取所需的包含标头名称,但问题出在以下两行:

    #define TOKENPASTE(x, y) x ## y
    #define PRODUCT_SPECIFIC_INCLUDE TOKENPASTE2(PRODUCT_SPECIFIC, __FILE__)
    

    __FILE__ : 此宏扩展为当前输入文件的名称, 以 C 字符串常量的形式

    TOKENPASTE(PRODUCT_SPECIFIC, __FILE__) |--> product ## "foo.h"

    product 和 " 永远不能提供有效的令牌。这就是 CPP 给你错误的原因。您需要将 文件名写为纯文本,以便您可以将其与其他宏结合使用。

    你可以这样做:

    #define TOKENPASTE(x) #x
    #define TOKENPASTE2(x) TOKENPASTE(x)
    #define PRODUCT_SPECIFIC_INCLUDE TOKENPASTE2(PRODUCT_SPECIFIC/foo.h)
    #include PRODUCT_SPECIFIC_INCLUDE
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-09
      • 2013-12-23
      • 2011-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多