------- Comment #13 from edwintorok at gmail dot com 2008-03-24 17:00 ------- (In reply to comment #11) > I think the code is violating alignment requirements of the C/C++ standard. >
First a real bug here is that -Wstrict-aliasing doesn't warn of this situation. Do you agree? Unaligned accesses is undefined in general, I agree. But on x86 it has always been possible to do unaligned accesses, and it is possible even with vector instructions (movdqu). Of course these are slower than aligned accesses, but there should be some way to express them in C [*] The most natural way to do that is to typecast, and this has worked, knowing that x86 doesn't have instructions that can SIGBUS/SIGSEGV on unaligned accesses (not true anymore with vector instructions), or knowing that compilers won't generate vectorized code for unaligned accesses (true until gcc-4.3 AFAIK). If you decide to handle unaligned accesses as undefined even for x86, the Linux kernel developers should be notified: The kernel has a macro, that is defined as such on x86: #define get_unaligned(ptr) (*(ptr)) And defined using these generically for non-x86 architectures struct __una_u32 { __u32 x __attribute__((packed)); }; static inline __u32 __uldl(const __u32 *addr) { const struct __una_u32 *ptr = (const struct __una_u32 *) addr; return ptr->x; } [*]: this can be used to express unaligned accesses safely And it is being used in a loop: http://lxr.linux.no/linux/net/bluetooth/bnep/core.c#L153 BTW, the original code for this bugreport does unaligned accesses only on little-endian architectures, and this has worked on all compilers until now: #if WORDS_BIGENDIAN == 0 .. #define cli_readint32(buff) (*(const int32_t *)(buff)) ... #else ... static inline int32_t cli_readint32(const char *buff) { int32_t ret; ret = buff[0] & 0xff; ret |= (buff[1] & 0xff) << 8; ret |= (buff[2] & 0xff) << 16; ret |= (buff[3] & 0xff) << 24; return ret; } ... #endif -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35653