История изменений
Исправление gentoo_root, (текущая версия) :
и char* можно приводить к любому типу не нарушая strict aliasing
Я читал стандарт и из того, что я понял, это не всегда правда. Если у объекта (куска памяти) есть декларированный тип, и это, например, char, то к нему нельзя обратиться, как к struct payload, потому что его эффективный тип тоже будет char, несовместимый со struct payload, тут нарушение. Если же мы буфер замаллочили и получили на него указатель char *, то декларированного типа у объекта не будет, а эффективный тип будет определяться типом lvalue, вызвавшим последнее изменение, если оно было, иначе типом текущего обращения, т.е. в данном случае можно смело алиасить выделенный динамически массив чаров и struct payload.
На некоторых платформах (в частности старые версии ARMов) попытка чтения скжем 32битного инта по адресу не кратному 4 приводит к крашу приложения (SIGBUS) (или 16бит по не четному адрессу).
Да, я в курсе, что такие архитектуры есть, и я слежу за тем, чтобы обращения были выравненными. Тем более даже на x86, где есть unaligned access, он более медленный.
Однако компилятор видет что short* не может быть алиасом ни для global (struct global* не может быть приведен к short*), ни для global.a (int* не совместим с short*) а значит строчка
*(short *)test = 'b';
не может модифецировать переменную global (поскольку разрешена оптимизация по strict aliase), а занчит можно производить оптимизацию возвращаемого значения (вернуть константу 'a' вместо чтения из памяти значения global.a).
Да, именно так этот пример и работает, во втором сообщении всё верно.
Исправление gentoo_root, :
и char* можно приводить к любому типу не нарушая strict aliasing
Я читал стандарт и из того, что я понял, это не всегда правда. Если у объекта (куска памяти) есть декларированный тип, и это, например, char, то к нему нельзя обратиться, как к struct payload, потому что его эффективный тип тоже будет char, несовместимый со struct payload, тут нарушение. Если же мы буфер замаллочили и получили на него указатель char *, то декларированного типа у объекта не будет, а эффективный тип будет определяться типом lvalue, вызвавшим последнее изменение, если оно было, иначе типом текущего обращения, т.е. в данном случае можно смело алиасить выделенный динамически массив чаров и struct payload.
На некоторых платформах (в частности старые версии ARMов) попытка чтения скжем 32битного инта по адресу не кратному 4 приводит к крашу приложения (SIGBUS) (или 16бит по не четному адрессу).
Да, я в курсе, что такие архитектуры есть, и я слежу за тем, чтобы обращения были выравненными. Тем более даже на x86, где есть unaligned access, он более медленный.
Однако компилятор видет что short* не может быть алиасом ни для global (struct global* не может быть приведен к short*), ни для global.a (int* не совместим с short*) а значит строчка
*(short *)test = 'b';
не может модифецировать переменную global (поскольку разрешена оптимизация по strict aliase), а занчит можно производить оптимизацию возвращаемого значения (вернуть константу 'a' вместо чтения из памяти значения global.a).
Да, именно так этот пример и работает, во втором сообщении всё верно.
Исходная версия gentoo_root, :
и char* можно приводить к любому типу не нарушая strict aliasing
Я читал стандарт и из того, что я понял, это не всегда правда. Если у объекта (куска памяти) есть декларированный тип, и это, например, char, то к нему нельзя обратиться, как к struct payload, потому что его эффективный тип тоже будет char, несовместимый со struct payload, тут нарушение. Если же мы буфер замаллочили и получили на него указатель char *, то декларированного типа у объекта не будет, а эффективный тип будет определяться типом lvalue, вызвавшим последнее изменение, если оно было, иначе типом текущего обращения, т.е. в данном случае можно смело алиасить выделенный динамически массив чаров и struct payload.
На некоторых платформах (в частности старые версии ARMов) попытка чтения скжем 32битного инта по адресу не кратному 4 приводит к крашу приложения (SIGBUS) (или 16бит по не четному адрессу).
Да, я в курсе, что такие архитектуры есть, и я слежу за тем, чтобы обращения были выравненными. Тем более даже на x86, где есть unaligned access, он более медленный.
Однако компилятор видет что short* не может быть алиасом ни для global (struct global* не может быть приведен к short*), ни для global.a (int* не совместим с short*) а значит строчка
*(short *)test = 'b';
не может модифецировать переменную global (поскольку разрешена оптимизация по strict aliase), а занчит можно производить оптимизацию возвращаемого значения (вернуть константу 'a' вместо чтения из памяти значения global.a).
Да, именно так этот пример и работает, во втором сообщении всё верно.