使用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))?
答案 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 ......