考虑以下包含动物类型的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处。
这个假设正确吗?可以将其视为未定义的行为吗?我特别担心跨平台的字节序差异。
我在stackoverflow上看到了关于工会的多个问题,但它们似乎都使用了不同大小的成员。我的会员人数为相同,我正在尝试保持这种方式。
答案 0 :(得分:2)
这个假设正确吗?可以
取决于sizeof Animals
。编译器可以选择在每个成员之间添加额外的填充。您可以提示编译器使用特定的填充,并使用_Static_assert
(C11)确保两个大小均匹配:
_Static_assert(sizeof(animals_list) == 2 * sizeof(Animals), "Sizes don't match.")
结构成员顺序由标准指定,但offsetof(S, member)
的结果不是。
尽管如此,匿名结构成员之间和animals_list
项之间可能存在的填充应该完全相同,因此它很可能在任何平台上都可以使用,但是语言规范并不能保证
答案 1 :(得分:1)
根据标准,arrayLValue[index]
等效于*(arrayLValue+index)
。 gcc和clang都不允许访问*(someUnion.arrayMember+index)
可能影响someUnion
的可能性。尽管gcc和clang似乎认识到对someUnion.arrayMember[index]
的访问可能会影响someUnion
,但是它们唯一允许行为与假定等效的*(someUnion.arrayMember+index)
有所不同的唯一方式是,如果标准没有不能定义两者的行为。