Как указать указатель, который указывает на невыровненный int?

struct Intx4 {
int data[4];
};

Intx4 loadIntx4(void const *p) {
auto up alignas(1) = (int const *)p; // Does this line correct? (compiled ok in clang)
Intx4 r;
for (int i = 0; i < 4; i++) r.data[i] = up[i];
return r;
}

Я также попробовал следующее, все они не смогли скомпилировать в Clang:

int const *up alignas(1) = (int const *)p;
auto up = (int const alignas(1) *)p;

1

Решение

Чтобы прочитать не выровненное целое число:

int i;
void* ptr_to_unaligned;
...
memcpy (&i, ptr_to_unaligned, sizeof(i));

В C ++ нет целочисленного типа без выравнивания, поэтому вы должны void*,

3

Другие решения

Попытка преобразовать указатель в void в тип с требованием выравнивания вызывает неопределенное поведение в соответствии с проектом C ++ 11 (n4296)

Из 5.2.9 Статического броска §13: Значение типа «указатель на cv1 void» может быть преобразовано в значение типа «указатель на cv2 T», где T
тип объекта и cv2 — это та же квалификация cv, что и cv1 или более высокая квалификация, чем cv1 … Если исходное значение указателя представляет
адрес A байта в памяти и A удовлетворяет требованию выравнивания T, тогда результирующий указатель
значение представляет собой тот же адрес, что и исходное значение указателя, то есть A. Результат любого другого такого преобразования указателя не определен
(подчеркните мой)

Я знаю, что вы используете явное приведение (или приведение в стиле C), но 5.4 явное приведение говорит: Преобразования, выполняемые const_cast (5.2.11), static_cast (5.2.9), static_cast, за которым следует const_cast, reinterpret_cast (5.2.10) или reinterpret_cast, за которым следует const_cast,
может выполняться с использованием приведенной нотации явного преобразования типов. Те же семантические ограничения и поведение применяются …

Так что в вашем случае явное приведение static_cast<int const *>(p),

Известно, что некоторые архитектуры, в частности, архитектура ARM, попадают в ловушку, когда вы пытаетесь получить доступ к не выровненным указателям int, как сказано в что другой так ответ

3

Чтобы использовать целое число без выравнивания, поместите слово __packed перед объявлением целочисленного указателя:

__packed int *pi; // pointer to unaligned int

Не выровненные указатели в коде C и C ++

0