Код на самом деле приводит к нескольким проблемам одновременно.Во-первых, как было сказано ранее, код нарушает правила псевдонимов и, следовательно, результат не определен для стандарта.Так что, строго говоря, компилятор может делать кучу вещей при оптимизации (это на самом деле ваш случай, когда вышеупомянутый код встроен).
Второй (и я считаю, что это и есть настоящая проблема здесь) - приведение char *к int * будет увеличивать предполагаемое выравнивание указателя.В соответствии с вашей платформой ABI, char может быть выровнен на 1 байт, а int - не менее 4 (double выровнен на 8 байт, кстати).Система может выдерживать невыровненные нагрузки, но не всегда, например, на arm / darwin она может выдерживать 4-байтовые невыровненные нагрузки, но не 8. Последний случай может произойти, когда компилятор решит объединить две последовательные нагрузки / сохраненные в 1. Так как выУдар по фактическому выравниванию компилятора указателя может сделать вывод, что все выровнено подходящим образом и сгенерировать 8-байтовые нагрузки.
Итак, вкратце - исправьте ваш код :) В этом конкретном случае вам поможет memcpy / memmove.