Это действительно нарушает правила строгого сглаживания?

Когда я скомпилирую этот пример кода с помощью g ++, я получаю это предупреждение:

предупреждение: разыменованный тип-караульный указатель нарушит правила строгого сглаживания [-Wstrict-aliasing]

Код:

 #include  int main() { alignas(int) char data[sizeof(int)]; int *myInt = new (data) int; *myInt = 34; std::cout << *reinterpret_cast(data); } 

В этом случае, не является ли alias data int, и поэтому возврат его обратно в int не будет нарушать строгие правила псевдонимов? Или я чего-то не хватает?

Edit: Странно, когда я определяю data следующим образом:

 alignas(int) char* data = new char[sizeof(int)]; 

Предупреждение компилятора исчезает. Выделяет ли распределение стека значение со строгим псевдонимом? Является ли тот факт, что это char[] а не char* означает, что он не может фактически быть псевдонимом любого типа?

Предупреждение абсолютно оправдано. Разложившийся указатель на data не указывает на объект типа int , и его литье не меняет этого. См. [Basic.life] / 7 :

Если после того, как срок жизни объекта закончился и перед хранилищем, который объект занят, повторно используется или выпущен, создается новый объект в месте хранения, в котором находился исходный объект, указатель, указывающий на исходный объект , ссылку, которая ссылается на исходный объект, или имя исходного объекта будет автоматически ссылаться на новый объект и, как только время жизни нового объекта будет запущено, можно использовать для управления новым объектом, если :
(7.1) – [..]
(7.2) – новый объект имеет тот же тип, что и исходный объект (игнорируя cv-квалификаторы верхнего уровня) ,

Новый объект не является массивом char , а int . P0137 , который формализует понятие направления, добавляет launder :

[ Примечание . Если эти условия не выполняются, указатель на новый объект может быть получен из указателя, который представляет адрес его хранилища, вызывая std::launder (18.6 [support.dynamic]). – конечная нота ]

Т.е. ваш fragment можно исправить следующим образом:

 std::cout << *std::launder(reinterpret_cast(data)); 

.. или просто инициализируйте новый указатель из результата размещения new, который также удаляет предупреждение.

Как насчет изменения

 std::cout << *reinterpret_cast(data); 

в

 int *tmp = reinterpret_cast(data); std::cout << *tmp; 

?

В моем случае он избавился от предупреждения.

Interesting Posts
Давайте будем гением компьютера.