Boost logo

Boost :

Subject: [boost] [Endian] Unaligned fields in packed structs
From: Phil Endecott (spam_from_boost_dev_at_[hidden])
Date: 2011-09-06 19:48:22

Dear All,

One of my all-time worst bugs was due to calling htonl() on an
unaligned field in a packed struct. It worked in debug mode but not in
production code, and there were no compiler warnings about the broken
alignment requirement. So I thought I'd try this:

inline void inplace_byteswap(uint32_t& val)
   val = (val>>24)
       | ((val>>8) & 0x0000ff00)
       | ((val<<8) & 0x00ff0000)
       | (val<<24);

struct S {
   uint16_t a;
   uint32_t b;
} __attribute__ ((packed));

int main()
   S s;
   s.b = 0x12345678;

This fails to compile: "error: cannot bind packed field ‘s.S::b’ to
‘uint32_t& {aka unsigned int&}’". So it's good that it doesn't just
fail unpredictably at runtime like my old nightmare, but it's not
ideal. If instead I write:

inline uint32_t byteswap(uint32_t val)
   return (val>>24)
        | ((val>>8) & 0x0000ff00)
        | ((val<<8) & 0x00ff0000)
        | (val<<24);

   s.b = byteswap(s.b);

then of course it does work; the unaligned accesses don't "escape" from
where the compiler knows about them and can apply fixups.

Anyway, before I tried this I was already wondering about the choice of
function signatures:

   void endian::reorder(T&); // in-place byteswap
   void endian::reorder(T src, T& dest); // out-of-place byteswap

What is the rationale (or precedent) for these and not

   T endian::reorder(T);


If sin(theta) returns its result, why shouldn't reorder(val) do so too?

Regards, Phil.

Boost list run by bdawes at, gregod at, cpdaniel at, john at