Объединения, псевдонимы и подбор текста на практике: что работает, а что нет?

У меня проблема с пониманием того, что можно, а что нельзя делать с помощью объединений с 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

Источник: ledsshop.ru

Стиль жизни - Здоровье!