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

save expanded macro result before it is undefined

对于 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)) ?

使用枚举:

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

您可以重写 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));

您无法根据需要扩展宏,因为您在应用宏之前取消定义了 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...