Как указать указатель, который указывает на невыровненный 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;
3 ответа
Чтобы прочитать невыровненное целое число:
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, что и или больше cv-квалификации, чем, 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, как сказано в другом ответе SO
Чтобы использовать целое число без выравнивания, поместите слово __packed перед объявлением целочисленного указателя:
__packed int *pi; // pointer to unaligned int