Ответ 1
Я нашел свой путь через лабиринт к некоторым великим источникам на этом, и я думаю, что у меня есть довольно полное резюме этого. Я отправляю это как ответ, потому что он, кажется, объясняет как (ИМО очень ошибочное) намерение предложения C, так и тот факт, что С++ не наследует его. Это со временем изменится, если я обнаружу дальнейший вспомогательный материал или изменения ситуации.
Это мой первый случай, когда мы пытаемся подвести очень сложную ситуацию, которая кажется нечеткой даже для многих языковых архитекторов, поэтому я буду приветствовать разъяснения/предложения о том, как улучшить этот ответ, или просто лучший ответ, если кто-либо имеет один.
Наконец, некоторые конкретные комментарии
Смутно связанные потоки, я нашел следующий ответ от @tab - и высоко оценил содержащиеся ссылки на (освещающие, если не убедительные) отчеты GCC и Рабочей группы о дефектах: fooobar.com/questions/94984/...
Ссылка GCC содержит некоторое интересное обсуждение и показывает значительную путаницу и противоречивые интерпретации со стороны Комитета и поставщиков компиляторов - вокруг темы union
member struct
s, punning и aliasing как в C, так и в С++.
В конце этого мы связаны с основным событием - другим потоком BugZilla, Ошибка 65892, содержащим чрезвычайно полезное обсуждение. В частности, мы находим путь к первому из двух ключевых документов:
Происхождение добавленной строки в C99
Предложение N685 является источником добавленного предложения относительно видимости объявления типа union
. Посредством того, что некоторые претензии (см. Поток GCС# 2) является полной неверной интерпретацией "общей исходной последовательности", N685 действительно был , чтобы разрешить релаксацию правил сглаживания для "общей исходной последовательности" struct
в рамках TU некоторых union
, содержащих экземпляры указанных struct
типов, как видно из этой цитаты:
Предлагаемое решение состоит в том, чтобы требовать, чтобы была видна декларация объединения если возможны псевдонимы через общую начальную последовательность (например, выше). Следовательно, следующий TU обеспечивает такой вид наложения, если это необходимо:
union utag {
struct tag1 { int m1; double d2; } st1;
struct tag2 { int m1; char c2; } st2;
};
int similar_func(struct tag1 *pst2, struct tag2 *pst3) {
pst2->m1 = 2;
pst3->m1 = 0; /* might be an alias for pst2->m1 */
return pst2->m1;
}
Судя по обсуждению GCC и комментариям ниже, таким как @ecatmur, это предложение, которое, по-видимому, требует спекулятивного разрешения псевдонимов для любого типа struct
, имеющего некоторый экземпляр внутри некоторого union
, видимого для этого TU - чтобы получить отличную насмешку и редко выполнялись.
Очевидно, насколько сложно было бы удовлетворить эту интерпретацию добавленного предложения без полного искажения многих оптимизаций - для небольшой выгоды, поскольку малое количество кодеров захотело бы этой гарантии, а те, кто это делает, могут просто включить fno-strict-aliasing
(что ИМО указывает на большие проблемы). Если это реализовано, это пособие с большей вероятностью поймает людей и ложно взаимодействует с другими объявлениями union
s, чем полезно.
Отсутствие строки из С++
Следуя этому и комментарию, который я сделал в другом месте, @Potatoswatter в этом ответе здесь, на SO, говорится, что:
Часть видимости была намеренно исключена из С++, потому что она широко считается смехотворной и нереализуемой.
Другими словами, похоже, что С++ сознательно избегал принятия этого добавленного предложения, вероятно, из-за его широко воспринимаемой абсурдности.. По просьбе "на запись", цитируя это, Potatoswatter предоставил следующее ключевая информация о участниках темы:
Люди в этом обсуждении, по сути, "находятся на записи". Эндрю Пински - хардкорный сторонник GCC. Мартин Себор является активным членом комитета C. Джонатан Вакели является активным членом комитета С++ и разработчиком языка/библиотеки. Эта страница является более авторитетной, ясной и полной, чем все, что я мог бы написать.
Potatoswatter, в том же потоке SO, который был связан выше, делает вывод о том, что С++ сознательно исключил эту строку, не оставляя специальной обработки (или, в лучшем случае, обработки, определенной реализацией) для указателей в общую начальную последовательность. Будет ли их лечение в будущем конкретно определено, по сравнению с любыми другими указателями, еще предстоит выяснить; сравните с моим заключительным разделом ниже о C. В настоящее время, однако, это не так (и снова IMO, это хорошо).
Что это значит для С++ и практических реализаций C?
Итак, с гнусной линией от N685... "отбросьте"... мы вернулись к предположению, что указатели на общую начальную последовательность не являются особыми с точки зрения сглаживания. Все еще. стоит подтвердить, что этот абзац на С++ означает без него. Ну, второй поток GCC над ссылками на другой камень:
С++ дефект 1719. Это предложение достигло статуса DRWP: "Проблема DR, разрешение которой отражено в текущем рабочем документе. Рабочий документ представляет собой проект для будущей версии стандарта" - cite. Это либо пост С++ 14, либо, по крайней мере, после окончательного проекта, который я здесь привел (N3797), и намеревается сделать значительным и, по моему мнению, осветить, переписать текст этого параграфа следующим образом. Я смелый, что я считаю важными изменениями, и {эти комментарии} являются моими:
В стандартном макете с активным членом { "active" указывает экземпляр
union
, а не только тип} (9.5 [class.union]) типа structT1
, разрешено читать {ранее "проверять" } нестатический элемент данныхm
другого члена объединения типа structT2
при условии, чтоm
является частью общая начальная последовательностьT1
иT2
. [Примечание: чтение изменчивого объекта через нелетучее значение glvalue имеет поведение undefined (7.1.6.1 [Dcl.type.cv]). -end note]
Это, по-видимому, разъясняет смысл старой формулировки: для меня это говорит о том, что любое специально разрешенное 'punning' среди union
member struct
с общими начальными последовательностями должно выполняться через экземпляр родительского union
- вместо того, чтобы основываться на типе structs
(например, указатели на них переданы некоторой функции). Эта формулировка, по-видимому, исключает любую другую интерпретацию, a la N685. Я бы сказал, что C будет хорошо принять это. Эй, говоря об этом, см. Ниже!
В результате получается, что - как хорошо продемонстрировано @ecatmur и в GCC-билетах - это оставляет такой union
member struct
по определению в С++ и практически на C, подчиняясь тем же строгим правилам псевдонимов как и любые другие 2 официально несвязанных указателя. Явная гарантия того, что вы можете прочитать общую начальную последовательность неактивного union
члена struct
, теперь более четко определена, не считая неопределенной и невообразимо утомительной для обеспечения соблюдения "видимость", как было предпринято N685 для C. В соответствии с этим определением основные компиляторы ведут себя как предназначенные для С++. Что касается C?
Возможное изменение этой строки в C/clarification в С++
Также очень важно отметить, что член комитета C Мартин Себор надеется, что это исправлено и на этом прекрасном языке:
Мартин Себор 2015-04-27 14:57:16 UTC Если кто-то из вас сможет объяснить проблему, я готов написать документ и представить его в РГ14 и запросить изменить стандарт.
Мартин Себор 2015-05-13 16:02:41 UTC У меня была возможность обсудить эту проблему с Кларком Нельсоном на прошлой неделе. Кларк работал над улучшением части псевдонимов спецификации C в прошлом, например, в N1520 (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1520.htm). Он согласился с тем, что, как и проблемы, упомянутые в N1520, это также является выдающейся проблемой, которая стоит для пересмотра и исправления РГ14 ".
Potatoswatter вдохновляет:
Комитеты C и С++ (через Мартина и Кларка) попытаются найти консенсус и выработать формулировку, чтобы стандарт мог наконец сказать, что это значит.
Мы можем только надеяться!
Снова, все дальнейшие мысли приветствуются.