在未定义之前保存扩展的宏结果
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...
对于 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...