【问题标题】:Generate non-stringified text literal macro at build time在构建时生成非字符串化文本字面量宏
【发布时间】:2018-05-06 20:27:12
【问题描述】:

背景

In a separate question of mine,我创建了一个类似函数的宏,它允许我连接用户提供的文本文字以创建宏名称,即:

/******************************************************************************
 * coconut.h
 ******************************************************************************/
#define COCONUT_FX_REGISTER (100)
#define COCONUT_BASE_REGISTER   (101)

/*******************************************************************************
 * pineapple.h
 ******************************************************************************/
#define PINEAPPLE_FX_REGISTER   (200)
#define PINEAPPLE_BASE_REGISTER (201)

/*******************************************************************************
 * test.c.
 ******************************************************************************/
#include <stdio.h>
#include "translation.h"
#include "coconut.h"
#include "pineapple.h"

int main(void) {

    int i = getTranslation(FX_REGISTER, COCONUT);
    printf("Translation:%d.\n", i);

    return 0;
}

/*******************************************************************************
 * translation.h
 ******************************************************************************/
#define getTranslation(x, y)  y ## _ ## x

目标

我想扩展这个逻辑,以便我可以使用宏作为默认值传递给getTranslation,即:

#define XFRM(x)         #x
#define XFRM2(x)        XFRM(x)
#define DEFAULT_PRODUCT     XFRM2(COCONUT)

int main(void) {

    int i = getTranslation(FX_REGISTER, DEFAULT_PRODUCT);
    printf("Translation:%d.\n", i);

    return 0;
}

问题

但是,我似乎无法将 DEFAULT_PRODUCT 转换为非字符串文本。


构建错误

main.c: In function ‘main’:
main.c:14:35: error: ‘DEFAULT_PRODUCT_FX_REGISTER’ undeclared (first use in this function)
  printf("%d\n", getTranslation(FX_REGISTER, DEFAULT_PRODUCT));
                                   ^
translation.h:33:25: note: in definition of macro ‘getTranslation’
 #define getTranslation(x, y) y ## _ ## x
                         ^
main.c:14:35: note: each undeclared identifier is reported only once for each function it appears in
  printf("%d\n", getTranslation(FX_REGISTER, DEFAULT_PRODUCT));
                                   ^
translation.h:33:25: note: in definition of macro ‘getTranslation’
 #define getTranslation(x, y) y ## _ ## x

问题

如何创建解析为非字符串文本文字的 DEFAULT_PRODUCT 宏,以便创建与 getTranslation 一起使用的“默认”值?这是使用设置为 C99 pedantic 的 GCC。

【问题讨论】:

    标签: c gcc macros c-preprocessor


    【解决方案1】:

    听起来像是 XY 问题。

    似乎宏连接是与宏字面扩展同时处理的,所以恐怕无法创建在getTranslation 之前扩展的DEFAULT_PRODUCT 宏。

    我的建议:再创建一个宏函数getDefaultTranslation(x),你就可以轻松实现你想要的了。

    // You may want to add appropriate comments
    // so code reviewers know what this is doing.
    #define getDefaultTranslation(x) COCONUT ## x
    

    关于this question,宏扩展是逐层进行的,同一层级联的优先级更高,所以再增加一层应该可以。请参阅下面的ringø's answer

    【讨论】:

      【解决方案2】:

      为了让预处理器在进行连接之前扩展宏,您需要添加一个间接方法

      #define CONCAT(a, b) a ## _ ## b
      
      #define getTranslation(x, y)  CONCAT(x,y)
      
      #define XFRM(x)         x
      #define XFRM2(x)        XFRM(x)
      #define DEFAULT_PRODUCT XFRM2(COCONUT)
      

      请注意,XFRM 已删除其 #(关闭 x),否则 " 会给出无效的预处理令牌。

      这样你就得到了

      int i = FX_REGISTER_COCONUT;
      

      【讨论】:

      • 你根本不需要XFRMXFRM2
      • 好吧,似乎 OP 添加了这些以显示一些宏扩展递归性。我保留它们以表明它仍然有效。
      猜你喜欢
      • 2014-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多