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;
Чтобы прочитать не выровненное целое число:
int i;
void* ptr_to_unaligned;
...
memcpy (&i, ptr_to_unaligned, sizeof(i));
В C ++ нет целочисленного типа без выравнивания, поэтому вы должны void*
,
Попытка преобразовать указатель в 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, как сказано в что другой так ответ
Чтобы использовать целое число без выравнивания, поместите слово __packed перед объявлением целочисленного указателя:
__packed int *pi; // pointer to unaligned int