Search code examples
cunions

Is accessing specific array indexes on a struct using an union undefined behavior?


Consider the following C struct declaration containing types of animals

typedef enum Animals { DOG, CAT, LION, ELEPHANT, HIPPO } Animals;

typedef struct {
    union {
        struct {
            Animals pet; /*!< Pet animals are stored at index 0 */
            Animals zoo; /*!< Zoo animals are stored at index 1 */
        };
        Animals animals_list[2];
    };
} AnimalsList;

I'd like to access the animals sometimes using the pet member or zoo member and sometimes to iterate over all animals using animals_list. I am expecting that pet will always be at index 0 of animals_list and zoo to be always at index 1 of animals_list.

Is this assumption correct? Can this be considered undefined behavior? In particular I'm concerned about endianness difference across platforms.

I saw multiple questions regarding unions on stackoverflow but they all seems to use members of different size. My members have the same size and I'm trying to keep it that way.


Solution

  • Is this assumption correct? Can

    Depends on the sizeof Animals. The compiler may choose to add extra padding between each member. You can hint the compiler to use a specific padding and use _Static_assert (C11) to make sure both sizes match:

    _Static_assert(sizeof(animals_list) == 2 * sizeof(Animals), "Sizes don't match.")
    

    The struct member order is specified by the standard, but the result of offsetof(S, member) is not.

    Nevertheless, the possibly-existing-padding should be exactly the same between the anonymous struct members and between the animals_list items, so it most likely will work on any platform, but there are no guarantees from the language specification.