Everyone seems to like using bit-fields in struct
s for this. Personally, I wrap all of my packet code in objects so that you don't see the guts. The problem that I have found with using bit-fields for protocol code is that it encourages using structures as overlays on memory. You can do this safely, but you have to be excruciatingly careful to ensure that you are properly dealing with endianess and packing issues. Unless you really have a good reason (e.g., you're writing the code that receives the Ethernet packet from the memory-mapped IO region), then using bit-fields overlaid on memory produces extremely fragile code IMHO.
I find it much easier to write a Packet
class that implements extraction, insertion, and overwriting routines in various bit widths. Then you implement your packet processing code in terms of extracting values of certain widths from offsets into native integers and what not. Hide all of the endianess and packing issues behind an abstraction until profiling proves that the overhead is too great to bear.
This is one of those lessons that I wish I had learned years ago... you might think that portability of code isn't a problem and neither is endianess. Trust me, the number of headaches that this causes you when your compiler changes its padding algorithm or you switch to a different compiler will convince you that overlays are a very bad idea for network packet processing code.