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;
   byteswap(s.b);
}

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 acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk