8

我试图将某些东西从使用 struct hack 转换为使用灵活的数组成员,结果却遇到以下错误消息:

错误:使用灵活数组成员的结构无效

(GCC 4.8.1, gnu99, MinGW)

在尝试追查消息的原因后,我将其提炼为以下相对最小的情况:

struct a {
    union {
        struct {
            int b;
            int c[];
        } d;
    } e;
};

换句话说,即使联合是结构的最后一个成员,具有灵活数组成员的结构也不能放入结构中的联合内。

(请注意,将灵活的数组成员直接放在联合似乎确实有效。)

现在:除了恢复到 struct hack(将 c 声明为长度为 1 的数组)之外,还有什么好的方法可以解决这个问题?指向联合内部结构的指针可以工作,但会受到额外的间接层。

4

2 回答 2

4

C11 标准 (ISO/IEC 9899:2011) 说:

§6.7.2.1 结构和联合说明符

¶18 作为一种特殊情况,具有多个命名成员的结构的最后一个元素可能具有不完整的数组类型;这称为灵活数组成员

在您的示例中,最后一个成员struct a不是灵活的数组成员。它是一个union包含一个struct具有灵活数组成员的 a。

但是,您必须非常努力地gcc抱怨;它需要-pedantic在编译器选项中。

于 2014-06-08T20:36:05.413 回答
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通过错误的联合成员进行访问,因为它是两个结构共享的公共初始序列的一部分。

于 2020-05-12T11:24:41.663 回答