Большинство компиляторов предлагают режим, в котором чтение и запись указателей будут воздействовать на базовое хранилище в той последовательности, в которой они выполняются, независимо от вовлеченных типов данных. Стандарт не требует, чтобы компиляторы предлагали такой режим, но, насколько я могу судить, это делают все качественные компиляторы.
Согласно их опубликованному обоснованию, авторы Стандарта добавили в язык ограничения на псевдонимы с заявленной целью избежать пессимистичных предположений компиляторов о псевдонимах при заданном коде, например:
float f;
float test(int *p)
{
f=1.0f;
*p = 2;
return f;
}
Обратите внимание, что в примере, приведенном в обосновании [очень похожем на вышеприведенное], даже если было законно изменить хранилище, используемое f
, с помощью указателя p
, разумный человек, глядя на код, не имел бы оснований полагать, что это вероятно. что-нибудь когда-нибудь случится. С другой стороны, многие разработчики компиляторов признали, что если дать что-то вроде:
float f;
float test(float *p)
{
f=1.0f;
*(int*)p = 2;
return f;
}
нужно быть намеренно тупым, чтобы думать, что код вряд ли изменит хранилище, используемое float
, и, следовательно, не было причин, по которым качественный компилятор не должен рассматривать запись в *(int*)p
как потенциальную запись в float
.
К сожалению, за прошедшие годы разработчики компиляторов стали все более агрессивно использовать «оптимизации» псевдонимов на основе типов, иногда таким образом, что они явно и бесспорно выходят за рамки того, что позволяет Стандарт. Если программе никогда не потребуется обращаться к какому-либо хранилищу как к разным типам в разное время, я бы предложил использовать параметр -fno-strict-aliasing
для компиляторов, которые его поддерживают. В противном случае можно иметь код, который соответствует Стандарту и работает сегодня, но не работает в будущей версии компилятора, которая стала еще более агрессивной со своими «оптимизациями».
PS — отключение псевдонимов на основе типов может повлиять на производительность кода в некоторых ситуациях, но правильное использование переменных и параметров с квалификациями restrict
позволит избежать затрат, связанных с пессимистичными предположениями о псевдонимах. С небольшой осторожностью использование этих квалификаторов позволит добиться той же оптимизации, что и агрессивное сглаживание, но гораздо более безопасно.
person
supercat
schedule
10.02.2017