Фон
Дискуссии о типичном характере типа-punning через union
, описывающем не типичную реализацию, типично цитируют следующие биты, здесь через @ecatmur (qaru.site/info/94985/...), на исключение для стандартного макета struct
, имеющего "общую начальную последовательность" типов членов:
C11 (6.5.2.3 Элементы структуры и объединения; Семантика):
[...], если объединение содержит несколько структур, которые имеют общую начальную последовательность (см. ниже), и если объект объединения в настоящее время содержит одну из этих структур, разрешается общая начальная часть любого из них где угодно, что декларация завершенный тип объединения виден. Две структуры разделяют общая исходная последовательность, если соответствующие члены имеют совместимые типы (а для битовых полей - одинаковые ширины) для последовательности одного или более начальных членов.
С++ 03 ( [класс .mem]/16):
Если POD-union содержит две или более POD-структуры, которые имеют общую начальную последовательность, и если объект POD-union в настоящее время содержит один этих POD-структур, разрешено проверять общие начальные часть любого из них. Две POD-структуры имеют общую начальную последовательность если соответствующие члены имеют совместимые с макетами типы (и для бит-поля, одинаковые ширины) для последовательности одного или нескольких начальных члены.
Другие версии двух стандартов имеют схожий язык; поскольку С++ 11 используемая терминология - это стандартная макета, а не POD.
Поскольку переинтерпретация не требуется, на самом деле это не типизация, а просто замена имени, примененная к union
доступ к элементам. Предложение для С++ 17 (печально известный P0137R1) делает это явным использованием языка как "доступ как будто был назначен другой член структуры".
Но обратите внимание на жирный шрифт ", где вид объявления завершенного типа объединения виден" - предложение, которое существует в C11, но нигде в проектах С++ для 2003, 2011 или 2014 (все почти идентичные, но более поздние версии заменяют "POD" новым стандартным макетом термина). В любом случае "видимое объявление бит типа union
полностью отсутствует в соответствующем разделе любого стандарта С++.
@loop и @Mints97, здесь qaru.site/info/94992/... - показывают, что эта строка также была отсутствующей на C89, впервые появившейся в C99 и оставаясь в C с тех пор (хотя, опять же, никогда не отфильтровывая до С++).
Обсуждения стандартов вокруг этого
[snipped - см. мой ответ]
Вопросы
Отсюда и мои вопросы:
-
Что это значит? Что классифицируется как "видимое объявление"? Был ли этот пункт предназначен для сужения или расширения - диапазона контекстов, в которых такое "наказание" определяло поведение?
-
Предполагаем ли мы, что это упущение в С++ очень преднамеренное?
-
В чем причина того, что С++ отличается от C?. С++ просто "наследовал" это от C89, а потом либо решил - или, что хуже, забыл - обновить рядом с C99?
-
Если разница является преднамеренной, то какие преимущества или недостатки существуют для двух разных обработок в C vs С++?
-
Что, если таковые имеются, интересные разветвления у него есть при компиляции или времени выполнения? Например, @ecatmur, в комментарии, отвечая на мое указание на его оригинальный ответ (ссылка как указано выше), предположил следующее.
Я бы предположил, что это позволяет более агрессивно оптимизировать; C может предположить, что аргументы функции
S* s
иT* t
не являются псевдонимами, даже если они совместно используют общая начальная последовательность, если нетunion { S; T; }
, в то время как С++ может сделать это предположение только во время связи. Может стоить задавая отдельный вопрос об этой разнице.
Ну, вот я, спрашиваю! Меня очень интересуют любые мысли об этом, особенно: другие соответствующие части (или) Стандарта, цитаты из членов комитета или других уважаемых комментаторов, идеи от разработчиков, которые, возможно, заметили практическую разницу из-за этого - при условии, что любой компилятор даже препятствует принудительному добавлению предложения C и т.д. Цель состоит в том, чтобы создать полезный каталог соответствующих фактов об этом предложении C и его (намеренное или нет) упущение с С++. Итак, отпусти!