Каждая версия стандартов C и C ++ на сегодняшний день была неоднозначной или противоречивой в отношении того, что можно сделать с адресами членов профсоюза. Авторы Стандарта C не хотели требовать, чтобы компиляторы допускали пессимистическую вероятность того, что функции могут быть вызваны такими конструкциями, как:
someFunction(&myUnion.member1, &myUnion.member2);
в тех случаях, когда функция вызовет значение, один член myUnion
будет изменен при доступе через другой. Хотя возможность получать адреса членов профсоюза была бы довольно бесполезной, если бы код не мог делать такие вещи, как:
someFunction1(&myUnion.member1);
someFunction2(&myUnion.member2);
someFunction3(&myUnion.member1);
авторы Стандарта ожидали, что качественные реализации, предназначенные для различных целей, будут обрабатывать конструкции, для которых Неопределенное Поведение "в документированной характеристике среды", когда это будет наилучшим образом служить этим целям, и, таким образом, считали, что создание поддержки для таких конструкций быть проблемой качества реализации было бы проще, чем пытаться сформулировать точные правила, для которых должны поддерживаться шаблоны. Компилятор, который сгенерировал код для вызываемых функций во втором примере, не зная их вызывающего контекста, не сможет чередовать доступы, выполняемые этими двумя функциями, и качественный компилятор, который расширил их встроенный во время обработки приведенного выше кода, не будет замечать этого. когда каждый указатель был получен из myUnion
.
Авторы Стандарта C89 не считают необходимым определять точные правила поведения указателей на члены объединения, потому что они думали, что желание авторов компиляторов создавать качественные реализации заставит их разумно обрабатывать соответствующие случаи даже без таких правил , К сожалению, некоторые авторы компиляторов были слишком ленивы, чтобы обрабатывать случаи, подобные второму примеру, приведенному выше, и вместо того, чтобы признать, что у качественных компиляторов не было никаких причин быть неспособными обрабатывать такие случаи, авторы более поздних стандартов C и C ++ склонялись над обратным придумать странно искаженные, неоднозначные и противоречивые правила, которые оправдывают такое поведение компилятора.
В результате оператор address-of следует рассматривать как значимо применимый к членам объединения только в тех случаях, когда результирующий указатель будет использоваться для доступа к отдельным байтам хранилища, либо с использованием непосредственного использования символьных типов, либо передачи таким функциям, как memcpy
, которые определены таким образом. Если или до тех пор, пока не произойдет существенное обновление Стандарта или приложения, описывающего средства, с помощью которых реализации могут предлагать необязательные гарантии, выходящие за рамки требований Стандарта, было бы лучше сделать вид, что члены объединения - как битовые поля - являются значениями, которые не у него есть адреса.