是否使用联合未定义行为访问结构上的特定数组索引?

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

考虑以下包含动物类型的 C 结构声明

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;

我想有时使用 pet 成员或 zoo 成员访问动物,有时使用 animals_list 遍历所有动物。我期望 pet 将始终位于 animals_list 的索引 0,并且 zoo 始终位于 animals_list 的索引 1。

这个假设是否正确?这可以被认为是未定义的行为吗?我特别担心跨平台的字节顺序差异。

我在 Whosebug 上看到了多个关于联合的问题,但它们似乎都使用 不同 大小的成员。我的成员有 相同的尺寸,我正在努力保持这种尺寸。

Is this assumption correct? Can

取决于 sizeof Animals。编译器可以选择在每个成员之间添加额外的填充。您可以提示编译器使用特定的填充并使用 _Static_assert (C11) 来确保两个大小匹配:

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

struct成员顺序是标准指定的,但是offsetof(S, member)的结果不是。

尽管如此,匿名结构成员之间和 animals_list 项之间可能存在的填充应该完全相同,因此它很可能适用于任何平台,但不能保证语言规范。

根据标准,arrayLValue[index] 等同于 *(arrayLValue+index)。 gcc 和 clang 都不允许访问 *(someUnion.arrayMember+index) 可能影响 someUnion 的可能性。虽然 gcc 和 clang 似乎认识到对 someUnion.arrayMember[index] 的访问可能会影响 someUnion,但如果标准没有,它们唯一允许与假定等效的 *(someUnion.arrayMember+index) 行为不同的方式'定义两者的行为。