Правила доступа типа в параграфе C раздела 6.5 проекта N1170 C11 не предусматривают, чтобы объект типа struct
или union
имел доступ к своему хранилищу с помощью чего-либо, кроме lvalue этого типа union
,lvalue другого типа, который содержит такой union
, или lvalue символьного типа.
Качественный компилятор, который может видеть, что указатель или lvalue одного типа используется для получения указателя или lvalueдругой, к которому затем осуществляется доступ, должен быть в состоянии распознать, что доступ к последнему, сделанный в контексте, где вывод является видимым, является доступом к первому.Я думаю, что авторы Стандарта думали, что достаточно очевидно, что это само собой разумеется, тем более что даже что-то вроде someUnion.intMember = 3;
будет вызывать UB в противном случае.Левый операнд присваивания является lvalue типа int
, и нет положения, позволяющего использовать lvalue типа int
для доступа к объекту типа объединения.Диапазон ситуаций, когда компилятор распознает, что доступ через производный указатель или lvalue является доступом к родительскому объекту, является проблемой качества реализации;Стандарт не дает указаний относительно того, что следует ожидать от «хорошей» реализации.
Что касается того, что позволяют clang и gcc, они, похоже, признают, что доступ к someUnion.someArray[i]
является доступом к объединению,но они не распознают *(someUnion.someArray+i)
аналогично, хотя Стандарт определяет две конструкции как эквивалентные.Поскольку Стандарт не требует , чтобы реализации распознавали (или даже очевидное someUnion.intMember
), несоответствие не делает Clang и GCC несоответствующими.Тем не менее, следует отметить, что они удивительно слепы, когда дело доходит до признания lvalues на основе союзов.