Я пытаюсь проверить некоторые из моих кодов для строгих нарушений псевдонимов, но это похоже, что я что-то пропустил, пытаясь понять строгий псевдоним Правило.
Представьте следующий код:
#include <stdio.h>
int main( void )
{
unsigned long l;
l = 0;
*( ( unsigned short * )&l ) = 1;
printf( "%lu\n", l );
return 0;
}
Классический и базовый пример. С GCC 4.9 (-Wall -fstrict-aliasing -Wstrict-aliasing -O3
) он сообщает об ошибке:
dereferencing type-punned pointer will break strict-aliasing rules
Но следующие компилируются отлично:
#include <stdio.h>
int main( void )
{
unsigned long l;
unsigned short * sp;
l = 0;
sp = ( unsigned short * )&l;
*( sp ) = 1;
printf( "%lu\n", l );
return 0;
}
В моем понимании, второй пример также нарушает правило сглаживания структуры.
Так почему он компилируется? Это вопрос точности в GCC, или я пропустил
что-то со строгим псевдонимом?
Я также нашел следующий раздел: Почему в этом коде не генерируются строгие сглаживания?
Компиляция с -Wstrict-aliasing=2
или -Wstrict-aliasing=3
не имеет значения.
Но -Wstrict-aliasing=1
сообщает об ошибке во втором примере.
Документация GCC говорит, что уровень 1 является наименее точным и может привести к многому ложных срабатываний, тогда как уровень 3 является наиболее точным...
Итак, что здесь происходит? Проблема с моим собственным пониманием или проблемой с GCC?
Бонусный вопрос
Я обычно предпочитаю Clang/LLVM над GCC для моих проектов, но, похоже, Clang
не выдает предупреждения о строгом псевдониме.
Кто-нибудь знает, почему?
Это потому, что он не способен обнаруживать нарушения, или потому, что он не следует
правило при генерации кода?