Это всегда было ненадежно. Как отмечали другие, сноска была добавлена в C99 через техническое исправление. Он гласит:
Если член, используемый для доступа к содержимому объекта объединения, не совпадает с членом, последним использовавшимся для хранения значения в объекте, соответствующая часть объектного представления значения переинтерпретируется как представление объекта в новом типе как описан в 6.2.6 (процесс, иногда называемый перфорацией). Это может быть ловушка.
Однако сноски указаны в Предисловии как ненормативные:
Приложения D и F составляют нормативную часть этого стандарта; приложения A, B, C, E, G, H, I, J, библиография и указатель предназначены только для информации. В соответствии с Частью 3 Директив ISO / IEC, это предисловие, введение, примечания, сноски и примеры также предназначены только для информации.
То есть сноски не могут запрещать поведение; они должны только прояснить существующий текст. Это непопулярное мнение, но процитированная выше сноска в этом отношении не соответствует действительности - такое поведение не запрещено в нормативном тексте. Действительно, есть противоречивые разделы, например 6.7.2.1:
... Значение не более одного из членов может быть сохранено в объекте union в любое время
В сочетании с 6.5.2.3 (относительно доступа к членам объединения с помощью оператора.):
Значение - это значение указанного члена.
Т.е. если значение только одного члена может быть сохранено, значение другого члена не существует. Это строго подразумевает, что каламбур типов с помощью объединения не должен быть возможен; доступ к члену дает несуществующее значение. Тот же текст все еще существует в документе C11.
Однако ясно, что цель добавления сноски заключалась в том, чтобы разрешить набор текста; просто комитет вроде бы нарушил правила в отношении сносок, не содержащих нормативный текст. Чтобы принять сноску, вам действительно нужно игнорировать раздел, в котором говорится, что сноски не являются нормативными, или иным образом попытаться выяснить, как интерпретировать нормативный текст таким образом, чтобы поддержать заключение сноски (что я пробовал, и не удалось, делать).
Лучшее, что мы можем сделать для ратификации сноски, - это сделать некоторые предположения об определении союза как набора перекрывающихся объектов из 6.2.5:
Тип объединения описывает перекрывающийся непустой набор объектов-членов, каждый из которых имеет необязательно указанное имя и, возможно, отдельный тип.
К сожалению, нет никаких подробностей о том, что подразумевается под перекрытием. Объект определяется как (3.14) область хранения данных в среде выполнения, содержимое которой может представлять значения (что одна и та же область хранения может быть идентифицирована двумя или более разными объекты подразумеваются приведенным выше определением перекрывающихся объектов, то есть объекты имеют идентичность, отличную от их области хранения). Разумным предположением является то, что члены объединения (конкретного экземпляра объединения) используют одну и ту же область хранения.
Даже если мы проигнорируем 6.7.2.1/6.5.2.3 и допустим, как следует в сноске, чтение любого члена объединения возвращает значение, которое будет представлено содержимым соответствующей области хранения - что, следовательно, позволит использовать каламбур - всегда -проблемное правило строгого псевдонима в 6.5 запрещает (с некоторыми незначительными исключениями) доступ к объекту, отличному от его типа. Поскольку доступ - это (3.1) 〈действие во время выполнения〉 для чтения или изменения значения объекта, и поскольку изменение одного из набора перекрывающихся объектов обязательно изменяет другие, то правило строгого псевдонима потенциально может быть нарушено запись члену союза (независимо от того, читается ли она потом другим или нет).
Например, по формулировке стандарта незаконными являются:
union {
int a;
float b;
} u;
u.a = 0; // modifies a float object by an lvalue of type int
int *pa = &u.a;
*pa = 1; // also modifies a float object, without union lvalue involved
(В частности, две закомментированные строки нарушают правило строгого алиасинга).
Строго говоря, сноска касается отдельного вопроса - чтения неактивного члена профсоюза; однако правило строгого алиасинга в сочетании с другими разделами, как указано выше, серьезно ограничивает его применимость и, в частности, означает, что оно не позволяет использовать каламбур в целом (но только для определенных комбинаций типов).
К сожалению, комитет, ответственный за разработку стандарта, похоже, намеревается, что каламбур шрифтов в целом возможен через объединение, и все же, похоже, не обеспокоен тем, что текст стандарта все еще запрещает это.
Стоит также отметить, что консенсусное понимание (поставщиками компиляторов) похоже на то, что каламбур типа через объединение разрешен, но доступ должен осуществляться через тип объединения (например, первая закомментированная строка в приведенном выше примере, но не вторая). Немного неясно, должно ли это применяться как для чтения, так и для записи, и никоим образом не поддерживается текстом стандарта (без учета сноски).
В заключение: несмотря на то, что в целом считается, что использование типов через объединение является законным (большинство считает, что это разрешено, только если доступ осуществляется через тип объединения, так сказать), формулировка стандарта запрещает его во всех, кроме некоторых тривиальных случаев. .
Цитируемый вами раздел:
Когда значение хранится в члене объекта типа union, байты представления объекта, которые не соответствуют этому члену, но соответствуют другим членам, принимают неопределенные значения.
... однако следует внимательно прочитать. Байты представления объекта , которые не соответствуют этому члену, относятся к байтам, превышающим размер члена, что само по себе не является проблемой для выбора типа (за исключением того, что вы не можете предполагать запись в член профсоюза оставит лишнюю часть любого большего члена нетронутой).
person
davmac
schedule
18.04.2016
float
в объединении с регистром FPU и его наложениемint
на регистр ЦП, а также чтение / запись этих регистров в / из памяти только тогда, когда это принудительноchar*
правилами наложения имен. - person supercat   schedule 09.07.2014