TLW
TLW

Reputation: 1439

C99: Flexible array inside union?

I tried to convert something from using the struct hack to using a flexible array member, only to run into the following error message:

error: invalid use of structure with flexible array member

(GCC 4.8.1, gnu99, MinGW)

After trying to track down the cause of the message, I distilled it down to the following relatively-minimal case:

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

In other words, a struct with a flexible array member doesn't see to be able to be put inside a union in a struct, even if the union is the last member of the struct.

(Note that putting a flexible array member directly inside the union does seem to work.)

Now: is there any good way to work around this besides reverting back to the struct hack (declaring c as an array of length 1)? A pointer to a struct inside the union would work, but suffers an additional layer of indirection.

Upvotes: 8

Views: 2587

Answers (2)

dpi
dpi

Reputation: 2006

The standard forbids this in section 6.7.2.1, Structure and union specifiers, paragraph 3:

A structure or union shall not contain a member with incomplete or function type [...], except that the last member of a structure with more than one named member may have incomplete array type; such a structure (and any union containing, possibly recursively, a member that is such a structure) shall not be a member of a structure or an element of an array.

A way around this would be to move the other elements of the outer struct into the inner structs, so that the outer struct is no longer necessary and the union can become the top-level element. For example, move the member mode of a struct like

struct item {
    int mode;
    union {
        struct {
            double a;
        } option1;
        struct {
            long b;
            int c[]; // not allowed
        } option2;
    };
};

to the top of each of the structs contained in the union:

union item {
    struct {
        int mode;
        double a;
    } option1;
    struct {
        int mode;
        long b;
        int c[];
    } option2;
};

Note that it is permitted to access mode through the wrong union member, because it is part of the common initial sequence that the two structs share.

Upvotes: 1

Jonathan Leffler
Jonathan Leffler

Reputation: 754030

The C11 standard (ISO/IEC 9899:2011) says:

§6.7.2.1 Structure and union specifiers

¶18 As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member.

In the example you have, the last member of struct a is not a flexible array member. It is a union containing a struct that has a flexible array member.

You have to work quite hard to get gcc to complain, though; it requires -pedantic amongst the compiler options.

Upvotes: 4

Related Questions