2017-04-12 68 views
9

我试图应用X Macro概念,以便有可能将所有结构成员初始化为自定义默认(无效)值。我写了下面的代码:为什么这个嵌套宏替换失败?

#define LIST_OF_STRUCT_MEMBERS_foo \ 
    X(a) \ 
    X(b) \ 
    X(c) 

#define X(name) int name; 
struct foo { 
    LIST_OF_STRUCT_MEMBERS_foo 
}; 
#undef X 


#define X(name) -1, 
static inline void foo_invalidate(struct foo* in) { 
    *in = (struct foo){ 
    LIST_OF_STRUCT_MEMBERS_foo 
    }; 
} 
#undef X 

#define X(name) -1, 
#define foo_DEFAULT_VALUE { LIST_OF_STRUCT_MEMBERS_foo } 
#undef X 

static struct foo test = foo_DEFAULT_VALUE; 

然而,当我运行预处理器的foo_DEFAULT_VALUE定义失败-1,

预处理器的输出来替代X(name)电话:

struct foo { 
    int a; int b; int c; 
}; 

static inline void foo_invalidate(struct foo* in) { 
    *in = (struct foo){ 
    -1, -1, -1, /*Here the substitution worked nicely*/ 
    }; 
} 

static struct foo test = { X(a) X(b) X(c) }; /*Why this substitution failed?*/ 

我想C-macros could refer to other macros 。你知道替代失败的原因吗?有什么解决方法吗?

我可以和foo_invalidate住在一起,但我不愿放弃直接在初始化时使用的值。

+2

你有''('name)'定义为'-1,'''define''foo_DEFAULT_VALUE'',但不是你真正使用它的地方。你需要在'static struct foo test = foo_DEFAULT_VALUE'行的周围定义'X'宏。 – Dmitri

回答

9

让我们假设我们是预处理并且遇到该行:

static struct foo test = foo_DEFAULT_VALUE; 

通1:

static struct foo test = { LIST_OF_STRUCT_MEMBERS_foo }; 

通2:

​​

通过3:没有扩大,因为此线上未定义X


一个解决办法可能是界定一个const变量(可能但不一定static)用作默认值:

#define X(name) -1, 
static const struct foo foo_DEFAULT_VALUE = { LIST_OF_STRUCT_MEMBERS_foo }; 
#undef X 

产生:

static const struct foo foo_DEFAULT_VALUE = { -1, -1, -1, }; 
+0

什么可能是一种解决方法?我想过以下几点,但我想知道它是否是最优的:'#define X(name)-1, #define foo_DEFAULT_VALUE_GENERATOR {LIST_OF_STRUCT_MEMBERS_foo} static const struct foo_DEFAULT_VALUE = foo_DEFAULT_VALUE_GENERATOR; #undef X' – Antonio

+0

那么,直截了当的方式显然是这样。将声明后面的'#undef'移动到行后面。否则需要重新设计。 –

+0

问题是X宏构造需要快速定义'X()'“......” – Antonio

2

你可能会喜欢X_Macros的undef-free版本,
它减少了在每次使用时定义和取消定义所需的小心
并在多个代码文件头UND使用率更适合定义:

#define LIST_OF_STRUCT_MEMBERS_foo(mode) \ 
    X_##mode(a) \ 
    X_##mode(b) \ 
    X_##mode(c) 

#define X_struct(name) int name; 
#define X_list(name) -1, 
#define foo_DEFAULT_VALUE { LIST_OF_STRUCT_MEMBERS_foo(list) } 

struct foo { 
    LIST_OF_STRUCT_MEMBERS_foo(struct) 
}; 

static inline void foo_invalidate(struct foo* in) { 
    *in = (struct foo){ 
    LIST_OF_STRUCT_MEMBERS_foo(list) 
    }; 
} 

static struct foo test = foo_DEFAULT_VALUE; 

输出(GCC-E):

struct foo { 
    int a; int b; int c; 
}; 

static inline void foo_invalidate(struct foo* in) { 
    *in = (struct foo){ 
    -1, -1, -1, 
    }; 
} 

static struct foo test = { -1, -1, -1, }; 
+0

非常有趣的方法!你从哪里知道的? – Antonio

+1

如果我说我发明了它,你会相信我吗?我并不是说我首先发明了它(早些时候可能有其他的),但是我确实自己想出了它。 – Yunnosch

+0

我确实相信你,昨天我搜索了很多主题,从来没有见过这样的实现!只要有可能,我会尽快给你赏金! – Antonio

-1

您也可以尝试检查扩展宏的输出。如果你使用gcc作为编译器,gcc -E <filename> >> full_src.txt'应该有所帮助。更多细节在这里:Seeing expanded C macros

+0

这正是我填写我的问题的'预处理器输出:'部分 – Antonio