在构建时生成非字符串化的文本文字宏

时间:2017-11-23 00:35:16

标签: c gcc macros c-preprocessor

背景

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宏,以便我可以创建一个&#34;默认&#34;与getTranslation一起使用的值?这是使用GCC设置为C99迂腐。

2 个答案:

答案 0 :(得分:2)

听起来像一个XY问题。

宏链接似乎与宏文字扩展同时处理,所以我担心没有办法创建在DEFAULT_PRODUCT之前展开的getTranslation宏。

我的建议:创建另一个宏功能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

答案 1 :(得分:1)

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

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