Casting a pointer to a different type with stricter alignment
requirements yields to implementation dependent behaviour.
Practicaly everything is fine for common platforms because the
CPU/OS/compiler will generate correct code, but anyhow it is
better to be safe than sorry.
Testing with dbg_hit_on() shows that the unalignment accesses are
very rare (below 0.1%) so it makes sense to split the code in a
fast path for the common case and a slower path as a fallback.
No functional change (verified with TB enabled).
const union { uint32_t i; char c[4]; } Le = { 0x01020304 };
const bool IsLittleEndian = (Le.c[0] == 4);
const union { uint32_t i; char c[4]; } Le = { 0x01020304 };
const bool IsLittleEndian = (Le.c[0] == 4);
+ T v;
+
+ if ((uintptr_t)addr & (alignof(T) - 1)) // Unaligned pointer (very rare)
+ std::memcpy(&v, addr, sizeof(T));
+ else
+ v = *((T*)addr);
+
if (LE != IsLittleEndian)
swap_byte(v);
return v;
if (LE != IsLittleEndian)
swap_byte(v);
return v;