是否使用联合未定义行为访问结构上的特定数组索引?
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)
行为不同的方式'定义两者的行为。
考虑以下包含动物类型的 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)
行为不同的方式'定义两者的行为。