假设我有一个结构定义如下:
struct entity {
int x;
int y;
};
以及将其用作成员的结构:
struct player {
struct entity position;
char* name;
};
如果我编写以下代码,则会出现错误:
struct player p;
p.x = 0; //error: 'struct player' has no member named 'x'
到目前为止,我一直在写一个函数,该函数接受播放器结构并通过执行return player.position.x
返回值。
是否有编译器标志或其他方法可让我“展平”结构(我不确定那是否是正确的短语)结构,并允许我像上面所示的那样访问x变量?我意识到,如果在播放器和实体中都存在一个名为x的整数,这可能是模棱两可的。
请注意,我将在多个结构中使用 entity 结构,因此我不能在 player 中使用匿名结构。
答案 0 :(得分:2)
简而言之,答案是“否”。如果您看过诸如What are anonymous structs and unions useful for in C11之类的问题却发现它们不是解决方案,则尤其如此。
有关常规的结构和联合类型的更多信息,您可以查看C11 §6.7.2.1 Structure and union specifiers(而有关匿名成员的更多信息,请参见¶13,例如,¶19)。我同意他们不是你所追求的;它们包含一个新定义的类型,该类型没有标签,也没有“声明列表”。
答案 1 :(得分:0)
您可以将其定义为MACRO:
#define ENTITY_MEMBERS int x; int y
struct entity{
ENTITY_MEMBERS;
}
struct player {
ENTITY_MEMBERS;
char* name;
};
实际上,这就是您在C中模仿C ++单一继承的方式。
答案 2 :(得分:0)
使用宏,我们可以创建一个类型生成器:
#define struct_entity(...) \
struct __VA_ARGS__ { \
int a; \
int b; \
}
然后我们可以随意将这种类型实例化为带标签的结构或匿名结构:
struct_entity(entity);
struct player {
struct_entity();
const char *name;
};
int main() {
struct player player;
player.a = 1;
player.b = 2;
player.name = "bar";
}
此代码的意图与您想要的更接近,并且没有approach of declaring just the structure members in the macro的UB问题。具体来说,struct player
内部有一个结构成员,而不是单个成员。这很重要,因为编译器可能会执行填充的减少和成员的重新排序-尤其是在嵌入式目标上。例如。下面的composite_1
和composite_2
不一定具有相同的布局!:
#include <assert.h>
#include <stddef.h>
typedef struct sub_1 {
int a;
void *b;
char c;
} sub_1;
typedef struct sub_2 {
void *d;
char e;
} sub_2;
typedef struct composite_1 {
int a;
void *b;
char c;
void *d;
char e;
} composite_1;
typedef struct composite_2 {
struct sub_1 one;
struct sub_2 two;
} composite_2;
// Some of the asserts below may fail on some architectures.
// The compile-time asserts are necessary to ensure that the two layouts are
// compatible.
static_assert(sizeof(composite_1) == sizeof(composite_2), "UB");
static_assert(offsetof(composite_1, a) == offsetof(composite_2, one.a), "UB");
static_assert(offsetof(composite_1, b) == offsetof(composite_2, one.b), "UB");
static_assert(offsetof(composite_1, c) == offsetof(composite_2, one.c), "UB");
static_assert(offsetof(composite_1, d) == offsetof(composite_2, two.d), "UB");
static_assert(offsetof(composite_1, e) == offsetof(composite_2, two.e), "UB");