LINUX.ORG.RU

История изменений

Исправление zaz, (текущая версия) :

Возможно я ошибаюсь, но любой тип можно приводить к char* и char* можно приводить к любому типу не нарушая strict aliasing. Но стоит помнить нюансы с масивами в C (о которых уже говорили) а именно

char buf[1024];
int *p1 = (int*)(buf); // WARNING buff is not a char*, buf is array
int *p2 = (int*)(&buf); // WARNING (same as above)
int *p3 = (int*)(&buf[0]); // OK, but some optimizations (-O3) cab broke this
int *p4 = (int*)((char*)(buf)); // OK

В вашем примере с struct global ошибка возникает не из-за strict aliasing, проблема возникает из-за агресивной оптимизации gcc (-O3) и неявному повторному изменению структуры global. volatile - решает данную проблему

struct global {
       int a;
} volatile  global;

Также стоит иметь ввиду причины возникновения strict aliasing, в принципе виной тому мобильные плотформы. На некоторых платформах (в частности старые версии ARMов) попытка чтения скжем 32битного инта по адресу не кратному 4 приводит к крашу приложения (SIGBUS) (или 16бит по не четному адрессу). В принципе это основная причина (плюс замутки с оптимизацией) по которой начал активно продвигатся strict aliasing. Но GCC позиционирует себя как лояльный к алиасингу компилятор, и он не генерирует варнинги если strict aliasing явно нарушен но данное нарушение безопасно (по мнению GCC).

Исходная версия zaz, :

Возможно я ошибаюсь, но любой тип можно приводить к char* и char* можно приводить к любому типу не нарушая strict aliasing. Но стоит помнить нюансы с масивами в C (о которых уже говорили) а именно

char buf[1024];
int *p1 = (int*)(buf); // WARNING buff is not a char*, buf is array
int *p2 = (int*)(&buf); // WARNING (same as above)
int *p3 = (int*)(&buf[0]); // OK, but some optimizations (-O3) cab broke this
int *p4 = (int*)((char*)(buf)); // OK

В вагем примере с struct global ошибка возникает не из-за strict aliasing, проблема возникает из-за агресивной оптимизации gcc (-O3) и неявному повторному изменению структуры global. volatile - решает данную проблему

struct global {
       int a;
} volatile  global;

Также стоит иметь ввиду причины возникновения strict aliasing, в принципе виной тому мобильные плотформы. На некоторых платформах (в частности старые версии ARMов) попытка чтения скжем 32битного инта по адресу не кратному 4 приводит к крашу приложения (SIGBUS) (или 16бит по не четному адрессу). В принципе это основная причина (плюс замутки с оптимизацией) по которой начал активно продвигатся strict aliasing. Но GCC позиционирует себя как лояльный к алиасингу компилятор, и он не генерирует варнинги если strict aliasing явно нарушен но данное нарушение безопасно (по мнению GCC).