Как указать указатель, который указывает на невыровненный 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

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

Другие вопросы по тегам