Доступ к определенным индексам массива в структуре использует объединенное неопределенное поведение? - PullRequest
4 голосов
/ 02 апреля 2019

Рассмотрим следующее объявление структуры 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 всегда будет с индексом 0 из animals_list и zoo всегда будет с индексом 1 из animals_list.

Это предположение верно?Можно ли считать это неопределенным поведением?В частности, я обеспокоен разницей порядка байтов на разных платформах.

Я видел несколько вопросов, касающихся союзов в stackoverflow, но все они, похоже, используют члены разного размера.У моих участников такого же размера , и я пытаюсь сохранить их таким образом.

Ответы [ 2 ]

2 голосов
/ 02 апреля 2019

Это предположение верно?Может

Зависит от sizeof Animals.Компилятор может выбрать добавление дополнительного отступа между каждым членом.Вы можете намекнуть компилятору использовать специальный отступ и использовать _Static_assert (C11), чтобы убедиться, что оба размера совпадают:

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

Порядок членов структуры определяется стандартом, но результат offsetof(S, member) is not.

Тем не менее, возможно, существующий отступ должен быть одинаковым между анонимными членами структуры и между элементами animals_list, поэтому он, скорее всего, будет работать на любой платформе, но нетгарантии из спецификации языка.

1 голос
/ 04 апреля 2019

Согласно стандарту, arrayLValue[index] эквивалентно *(arrayLValue+index).Ни gcc, ни clang не допустят, что доступ к *(someUnion.arrayMember+index) может повлиять на someUnion.В то время как gcc и clang, похоже, признают, что доступ к someUnion.arrayMember[index] может повлиять на someUnion, они могут вести себя иначе, чем предположительно эквивалентный *(someUnion.arrayMember+index), если бы Стандарт не определял поведениелибо.

...