How to specify a pointer which points to unaligned int?

2.3k Views Asked by At
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;
}

I also tried the followings, they all failed to compile in clang:

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

There are 3 best solutions below

0
On

To read an unaligned integer:

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

There is no unaligned integer type in C++, so you have to make do with void*.

2
On

Trying to convert a pointer to void to a type with alignment requirement invokes undefined behaviour, according to C++11 draft (n4296)

From 5.2.9 Static cast §13 : A prvalue of type “pointer to cv1 void” can be converted to a prvalue of type “pointer to cv2 T,” where T is an object type and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1... If the original pointer value represents the address A of a byte in memory and A satisfies the alignment requirement of T, then the resulting pointer value represents the same address as the original pointer value, that is, A. The result of any other such pointer conversion is unspecified (emphasize mine)

I know you are using an explicit cast (or C-style cast), but 5.4 Explicit cast says: The conversions performed by a const_cast (5.2.11), a static_cast (5.2.9), a static_cast followed by a const_cast, a reinterpret_cast (5.2.10), or a reinterpret_cast followed by a const_cast, can be performed using the cast notation of explicit type conversion. The same semantic restrictions and behaviors apply...

So in your case, the explicit cast is the same of static_cast<int const *>(p).

And some architectures, notably ARM architecture are know to trap when you try to access unaligned int pointers as said in that other SO answer

0
On

To use an integer in an unaligned way, put the word __packed in front of the integer pointer declaration:

__packed int *pi; // pointer to unaligned int

Unaligned pointers in C and C++ code