Звонок на memcpy
в порядке. Здесь у вас есть неопределенное поведение:
printf("%s\n", arr);
Спецификатор формата %s
ожидает аргумент char *
, но вы передаете uint32_t *
. Такое несоответствие аргумента - неопределенное поведение. Два типа указателей могут иметь одинаковое представление в вашей системе, но это не обязательно верно в общем случае.
Даже если типы совпадают, вы бы все еще имели бы UB, потому что arr
недостаточно велик, чтобы содержать строку "HelloWorld!Hell!"
. Эта строка (включая нулевой завершающий байт) имеет ширину 17 байт, поэтому нулевой терминатор не копируется. Затем printf
читает после конца массива, который является UB.
В качестве примера я изменил список переменных следующим образом:
uint32_t x = 0x11223344;
uint32_t arr[4] = { 1, 2, 3, 4 };
uint32_t y = 0x55667788;
И получил следующий вывод:
HelloWorld!Hell!�wfU
Что касается этого:
char *arr1 = (char *)arr;
Это допустимо, поскольку указатель одного типа объекта может быть преобразован в указатель на другой тип объекта. Кроме того, поскольку типом назначения является char *
, разрешается разыменовывать этот указатель для доступа к базовым байтам исходного объекта.