说我有一些结构:
#define FILL(instance, field, value) \
do { \
instance.#field = value; \
instance.has_#field = 1; \
} while(0); \
我想编写一个像
这样的宏struct mything1 x; FILL(x, foo, 5);
所以我可以去Send the token to another user Sharing Realm Between Users.
1.Send the token to another user via any method.
但是当我尝试编译它时这不起作用。这有可能吗?这是否可取?
GCC特定的非便携式解决方案很好。
答案 0 :(得分:4)
您正在将field
字符串化为"field"
,而不是通过其标识符引用该字段。请注意,令牌连接是使用##
完成的,而不是#
。一个小修复:
#define FILL(instance, field, value) \
do { \
instance.field = value; \
instance.has_##field = 1; \
} while(0)
我还在while(0)
之后删除了分号。该习惯用于通过在使用宏完成语句后使用分号来使FILL(x, foo, 5);
工作。否则,你最终会得到一个可以引发警告的尾随空语句。
答案 1 :(得分:2)
这是一个" XY问题"。没有理由使用宏,这只是简单的混淆。不要这样做。
相反,只需使用指定的初始值设定项:
struct mything1 x =
{
.foo = 5
};
如果你想要" has_foo"同时设置,考虑用适当的设计解决这个问题:
typedef struct
{
int value;
bool exists;
} thing_t;
typedef struct
{
thing_t foo;
thing_t bar;
} many_things_t;
many_things_t things =
{
.foo = {5, true}
};
作为最后的手段,如果你真的坚持使用结构并且你真的必须有一个宏而不是一个函数,由于原因未知,那么至少使用标准约定如何写这样的宏。
在这种情况下,使用" X宏"可能是明智的,因为它们是为避免代码重复而设计的。您可以列出字段名称和初始值设定项:
#define THING_LIST \
X(foo, 5) \
X(bar, 7)
完整示例:
#include <stdio.h>
struct mything1 {
int foo;
int has_foo;
int bar;
int has_bar;
};
#define THING_LIST \
X(foo, 5) \
X(bar, 7)
int main()
{
struct mything1 thing =
{
#define X(field, value) \
.field = value, \
.has_##field = 1,
THING_LIST
#undef X
};
printf("foo: %d has_foo: %d\n", thing.foo, thing.has_foo);
printf("bar: %d has_bar: %d\n", thing.bar, thing.has_bar);
}