在未定义之前保存扩展的宏结果

时间:2016-02-16 13:16:47

标签: c macros c-preprocessor stringification

使用GCC,我使用X-macros来收集变量。

#define TEST_MAP    \
        X(0, 1, 2)  \
        X(0, 2, 2)  \
        X(0, 3, 5)

假设我需要总结所有第二个字段

#define X(a,b,c) (+b)   /* sum all 2nd elements of TEST_MAP */
uint16_t d = (TEST_MAP);
#undef X

这很好,因为TEST_MAP扩展为

uint16_t d = ((+1) (+2) (+3));

但是,我更喜欢使用编译时常量,但如果我这样做

#define X(a,b,c) (+b)   /* sum all 2nd elements of TEST_MAP */
#define D (TEST_MAP)
#undef X

uint16_t d = D;

当然它不会起作用,因为在D扩展时X不再被定义,所以我有:

uint16_t d = (X(0, 1, 2) X(0, 2, 2) X(0, 3, 5));

我已经检查了#和##的使用,但我还没有找到如何解决这个问题。如何强制#define D扩展为((+ 1)(+ 2)(+ 3))?

3 个答案:

答案 0 :(得分:3)

使用枚举:

#define X(a,b,c) (+b)   /* sum all 2nd elements of TEST_MAP */
enum { D = (TEST_MAP) };
#undef X

答案 1 :(得分:2)

您可以重写X宏,以便X是宏的参数:

#define TEST_MAP(X) \
        X(0, 1, 2)  \
        X(0, 2, 2)  \
        X(0, 3, 5)

然后,您可以传递相应的宏(必须使用三个参数),而不必重复#define#undef X:

#define COL1(a, b, c) + (a)
#define COL2(a, b, c) + (b)
#define COL3(a, b, c) + (c)
#define SUM(a, b, c) + (a) + (b) + (c)

#define D1 (TEST_MAP(COL1));
#define D2 (TEST_MAP(COL2));
#define D3 (TEST_MAP(COL3));
#define S (TEST_MAP(SUM));

答案 2 :(得分:0)

您无法根据需要展开宏,因为您在应用它之前取消定义了X宏:

#define X(a,b,c) (+b)   /* sum all 2nd elements of TEST_MAP */

#define D (TEST_MAP)
#undef X               //You undefine X here before usage

uint16_t d = D;        //Here X doesn't exist anymore and can't expand.

考虑到预处理器在遇到宏时执行扩展,那时必须定义所有子宏。
要按照您的要求使用宏,您只需在使用后取消定义宏X 见样本:

#include <stdio.h>

#define TEST_MAP    \
        X(0, 1, 2)  \
        X(0, 2, 2)  \
        X(0, 3, 5)
#define D (TEST_MAP)

#define X(a,b,c) +(b)   /* sum all 2nd elements of TEST_MAP */
int d = (TEST_MAP);
#undef X

int main(void)
{
    #define X(a,b,c) +(b)   /* sum all 2nd elements of TEST_MAP */
    printf("Sum of 2nd -> %d - %d\n", d, D);
    #undef X
    #define X(a,b,c) +(c)   /* sum all 3rd elements of TEST_MAP */
    printf("Sum of 3rd -> %d\n", D);
    #undef X
    return 0;
}

或者您可以简单地恢复预处理器命令的顺序:

    #undef X
    #define X(a,b,c) +(b)   /* sum all 2nd elements of TEST_MAP */

在这种情况下,最后一个分配是一个新的undefine / redefine ......