Подтвердить что ты не робот

Строгое правило сглаживания и указатели char * '

Принятый ответ Что такое строгое правило псевдонимов? упоминает, что вы можете использовать char * для псевдонима другого типа, но не в другом.

Мне это не имеет смысла - если у нас есть два указателя, один из типов char * и другой тип struct something *, указывающий на одно и то же место, как возможно, что первые псевдонимы - второй, а второй не является первым?

4b9b3361

Ответ 1

Формулировка в указанном ответе немного ошибочна, так что сначала попробуем это: Один объект никогда не псевдонизирует другой объект , но два указателя могут "псевдоним" одного и того же объекта (что означает, что указатели указывают на одно и то же место памяти - как указывал М. М., это еще не 100% правильная формулировка, но вы получаете Идею). Кроме того, стандарт сам по себе (насколько мне известно) фактически говорит о строгом псевдониме вообще, но дает только правила, через какие виды выражений можно получить доступ к объекту или нет. Компиляторы, такие как '-fno-strict-aliasing', сообщают компилятору, может ли он предположить, что программист выполнил эти правила (чтобы он мог выполнять оптимизацию на основе этого предположения) или нет.

Теперь на ваш вопрос: любой объект можно получить с помощью указателя до char, но char объект (особенно a char) может быть недоступен через большинство других типов указателей. Исходя из этого, компилятор может/должен сделать следующие предположения:

  • Если тип самого фактического объекта неизвестен, char* и T* всегда могут указывать на один и тот же объект (псевдоним друг друга) → симметричные отношения.
  • Если T1 и T2 не связаны друг с другом, а не char, то T1* и T2* никогда не могут указывать на тот же объект → симметричное отношение
  • A char* может указывать на объект char OR a T
  • A T* не может указывать на объект char a симметричное отношение

Я считаю, что основное обоснование асимметричных правил доступа к объекту через указатели состоит в том, что массив char может не удовлетворять требованиям выравнивания, например. a int.

Таким образом, даже без оптимизации компилятора, основанной на правиле строгого псевдонимов, например, запись int в расположение массива char размером 4 байта по адресам 0x1,0x2,0x3,0x4x4 - в лучшем случае - приведет к низкой производительности и - в худшем случае - к другому местоположению памяти, потому что инструкции CPU могут игнорировать младшие два бита адреса при записи 4-байтового значения (так что здесь это может привести к записи в 0x0,0x1,0x2 и 0x3).

Также помните, что значение "родственный" отличается от языка к языку (между C и С++), но это не относится к вашему вопросу.

Ответ 2

если у нас есть два указателя, один из типов char * и другой типа struct something *, указывающий на одно и то же место, как возможно, что первые псевдонимы второго, а второго не имеют псевдоним первого?

Он делает, но это не точка.

Дело в том, что если у вас есть один или несколько struct something, вы можете использовать char* для чтения своих составляющих байтов, но если у вас есть один или несколько char, вы можете не использовать struct something* для прочитайте их.

Ответ 3

если у нас есть два указателя, один из типов char * и другой типа struct something *, указывающий на одно и то же место, как возможно, что первые псевдонимы второго, а второго не имеют псевдоним первого?

Указатели не псевдонимы друг друга; это небрежное использование языка. Алиасинг - это когда lvalue используется для доступа к объекту другого типа. (Разыменование указателя дает lvalue).

В вашем примере важно, чтобы тип объекта был псевдонимом. Для конкретного примера предположим, что объект является double. Доступ к double путем разыменования a char *, указывающий на double, является прекрасным, поскольку это допускает правило строгого псевдонижа. Однако доступ к double путем разыменования a struct something * недопустим (если, возможно, структура не начинается с double!).

Если компилятор ищет функцию, которая принимает char * и struct something *, и в ней нет информации об объекте, на который указывает (это на самом деле маловероятно, поскольку пропуски сглаживания выполняются в цельной программе этап оптимизации); то это должно было бы позволить возможность того, что объект действительно может быть struct something *, поэтому в этой функции не может быть оптимизации.