我尝试将某些内容从使用struct hack转换为使用灵活的数组成员,只是遇到以下错误消息:
错误:无效使用具有灵活数组成员的结构
(GCC 4.8.1,gnu99,MinGW)
在尝试追踪消息的原因后,我将其提炼为以下相对最小的情况:
struct a {
union {
struct {
int b;
int c[];
} d;
} e;
};
换句话说,具有灵活数组成员的结构看不到能够放入结构中的并集内,即使联合是结构的最后一个成员。
(请注意,将一个灵活的数组成员直接放在union 中似乎可以正常工作。)
现在:除了恢复结构黑客(将c声明为长度为1的数组)之外,还有什么方法可以解决这个问题吗?指向联合内部结构的指针可以工作,但是会遇到额外的间接层。
答案 0 :(得分:3)
C11标准(ISO / IEC 9899:2011)说:
§6.7.2.1结构和联合说明符
¶18作为一种特殊情况,具有多个命名成员的结构的最后一个元素可以 有一个不完整的数组类型;这称为灵活的数组成员。
在您拥有的示例中,struct a
的最后一个成员不是灵活的数组成员。它是union
,包含struct
,具有灵活的数组成员。
你必须努力工作才能让gcc
抱怨;它在编译器选项中需要-pedantic
。
答案 1 :(得分:1)
该标准在6.7.2.1节结构和联合说明符的第3段中禁止这样做:
结构或联合不得包含具有不完整或函数类型[]的成员,除非 具有多个命名成员的结构的最后一个成员可能具有不完整的数组类型; 这样的结构(以及可能(以递归方式包含)这样的成员的任何联合) 不得是结构的成员或数组的元素。
解决此问题的一种方法是将外部结构的其他元素移入内部结构,这样就不再需要外部结构,并且联合可以成为顶层元素。例如,移动
之类的结构的成员mode
struct item {
int mode;
union {
struct {
double a;
} option1;
struct {
long b;
int c[]; // not allowed
} option2;
};
};
位于联合体中每个结构的顶部:
union item {
struct {
int mode;
double a;
} option1;
struct {
int mode;
long b;
int c[];
} option2;
};
请注意,允许它通过错误的联合成员访问mode
,因为它是两个结构共享的常见初始序列的一部分。