У меня проблема с пониманием того, что можно, а что нельзя делать с помощью объединений с GCC. Я прочитал вопросы (в частности, здесь и здесь), но они фокусируются на стандарте C ++, я чувствую несоответствие между стандартом C ++ и практикой (обычно используемыми компиляторами).
В частности, недавно я обнаружил сбивающую с толку информацию в онлайн-документе GCC при чтении о флаге компиляции -fstrict-aliasing. Он говорит:
-fstrict-aliasing
Позвольте компилятору принять самые строгие правила псевдонима, применимые к компилируемому языку. Для C (и C ++) это активирует оптимизацию в зависимости от типа выражений. В частности, предполагается, что объект одного типа никогда не находится по тому же адресу, что и объект другого типа, если только типы почти не совпадают. Например,
unsigned intможет быть псевдонимомint, но неvoid*илиdouble. Тип символа может быть псевдонимом любого другого типа. Обратите особое внимание на такой код:union a_union { int i; double d; }; int f() { union a_union t; t.d = 3.0; return t.i; }Распространена практика чтения от другого члена профсоюза, чем тот, которому в последний раз писали (так называемая «каламбур»). Даже с -fstrict-aliasing разрешено использование символов при условии, что доступ к памяти осуществляется через тип объединения. Итак, приведенный выше код работает так, как ожидалось.
Вот что я понял из этого примера и своих сомнений:
1) псевдонимы работают только между похожими типами или char
Следствие 1): алиасинг — как следует из этого слова — это когда у вас есть одно значение и два члена для доступа к нему (то есть одни и те же байты);
Сомнение: ли два типа похожи, если они имеют одинаковый размер в байтах? Если нет, то какие бывают похожие типы?
Следствие 1) для несхожих типов (что бы это ни значило), алиасинг не работает;
2) каламбур — это когда мы читаем член, отличный от того, которому мы писали; это обычное дело, и оно работает должным образом, пока доступ к памяти осуществляется через тип объединения;
Сомнение: псевдоним — это конкретный случай каламбура, когда типы похожи?
Я запутался, потому что там говорится, что unsigned int и double не похожи, поэтому сглаживание не работает; затем в примере это псевдоним между int и double, и он четко говорит, что работает так, как ожидалось, но называет это каламбуром: не потому, что типы похожи или не похожи, а потому, что он читает из члена, который не записывал. Но я понял, что псевдонимы предназначены для чтения от члена, которого он не писал (как следует из этого слова). Я потерялся.
Вопросы: может ли кто-нибудь прояснить разницу между псевдонимом и каламбуром, и какое использование этих двух методов работает должным образом в GCC? А что делает флаг компилятора?
Я чувствую несоответствие между спецификациями и практикой, пока вы не обновите свой компилятор и все не нанесет ущерб! (правдивая история) — person L.C. schedule 19.02.2019
Когда вам действительно нужно набирать текст: stackoverflow.com/a/17790026/8120642 — person L.C. schedule 19.02.2019
