Согласно сноске 88 в проекте C11 N1570, «правило строгого наложения имен» (6.5p7) предназначено для указания обстоятельств, при которых компиляторы должны учитывать возможность того, что вещи могут иметь псевдонимы, но не пытаются определить, чтопсевдоним равен .Где-то вдоль линии появилось распространенное мнение, что доступы, отличные от определенных правилом, представляют собой «псевдонимы», а разрешенные - нет, но на самом деле верно обратное.
Учитывая такую функцию, как:
int foo(int *p, int *q)
{ *p = 1; *q = 2; return *p; }
В разделе 6.5p7 не говорится, что p
и q
не будут псевдонимами, если они идентифицируют одно и то же хранилище.Скорее, он указывает, что им разрешено для псевдонима.
Обратите внимание, что не все операции, связанные с доступом к хранилищу одного типа в качестве другого, представляют псевдонимы.Операция над lvalue, которая только что визуально получена из другого объекта, не "псевдоним" этого другого объекта.Вместо этого он является операцией над этим объектом.Псевдоним возникает, если между временем создания ссылки на какое-либо хранилище и временем его использования на то же хранилище ссылаются каким-либо образом , не полученным из первого , или код входит в контекст, в котором это происходит.
Хотя способность распознавать, когда lvalue является производной от другого, является проблемой качества реализации, авторы Стандарта должны были ожидать, что реализации распознают некоторые конструкции, выходящие за рамки мандата.Нет общего разрешения на доступ к любому хранилищу, связанному со структурой или объединением, с использованием lvalue типа member, и ничего в Стандарте прямо не указано, говорит , что операция, включающая someStruct.member
, должна быть распознана какоперация на someStruct
.Вместо этого, авторы Стандарта ожидали, что авторы компиляторов, которые предпринимают разумные усилия для поддержки конструкций своих клиентов, должны располагать лучшими возможностями, чем Комитет, чтобы оценивать потребности этих клиентов и удовлетворять их.Поскольку любой компилятор, который предпринимает даже отдаленно разумные усилия для распознавания производных ссылок, заметил бы, что someStruct.member
является производным от someStruct
, авторы Стандарта не видели необходимости явно указывать это.
К сожалению,обработка таких конструкций, как:
actOnStruct(&someUnion.someStruct);
int q=*(someUnion.intArray+i)
эволюционировала из "Достаточно очевидно, что actOnStruct
и разыменование указателя должны действовать на someUnion
(и, следовательно, на все его элементы), что нетнужно предписывать такое поведение "to" Поскольку стандарт не требует, чтобы реализации признавали, что вышеуказанные действия могут повлиять на someUnion
, любой код, основанный на таком поведении, нарушен и не нуждается в поддержке ".Ни одна из вышеперечисленных конструкций не поддерживается надежно gcc или clang, за исключением режима -fno-strict-aliasing
, хотя большинство «оптимизаций», которые будут заблокированы их поддержкой, будут генерировать код, который «эффективен», но бесполезен.
Если вы используете -fno-strict-aliasing
на любом компиляторе, имеющем такую опцию, почти все будет работать.Если вы используете -fstrict-aliasing
в icc, он будет пытаться поддерживать конструкции, использующие типизацию без псевдонимов, хотя я не знаю, есть ли какая-либо документация о том, какие конструкции он выполняет или не обрабатывает.Если вы используете -fstrict-aliasing
на gcc или clang, все, что работает, является чисто случайным.