为什么这个嵌套的宏替换失败了?

时间:2017-04-12 15:10:34

标签: c macros initialization c-preprocessor

我正在尝试应用X Macro概念,以便可以将所有struct成员初始化为自定义默认(无效)值。我写了以下代码:

#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的定义无法用X(name)替换-1,次调用

预处理器输出:

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一起生活,但是我不愿意放弃在初始化时直接使用值的一步。

3 个答案:

答案 0 :(得分:9)

让我们假装我们是预处理器并遇到这条线:

static struct foo test = foo_DEFAULT_VALUE;

通过1:

static struct foo test = { LIST_OF_STRUCT_MEMBERS_foo };

通过2:

static struct foo test = { X(a) X(b) X(c) };

传递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, };

答案 1 :(得分:2)

您可能喜欢X_Macros的无免费版本,
它减少了在每次使用时定义和取消定义所需的必要护理 并且更适合在多个代码文件中的头文件和用法中进行定义:

#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, };

答案 2 :(得分:-1)

您也可以尝试检查扩展宏的输出。如果您使用gcc作为编译器,gcc -E <filename> >> full_src.txt'将有所帮助。更多详情请点击此处:Seeing expanded C macros