Wireshark-dev: Re: [Wireshark-dev] C Bitfield types and alignment

From: Bill Meier <wmeier@xxxxxxxxxxx>
Date: Mon, 05 Dec 2011 16:41:07 -0500
My curiosity was piqued by Guy's comment in SVN #40078:

"Bitfields indicate how many bits they are; "guint8 foo:4" is
 self-contradictory (it's 4 bits, not 8).  Furthermore, the C language
 doesn't support "unsigned char" as a bitfield type;some compilers might
 accept that, but if you crank up the warning levels, even GCC will warn
 about that."

So: I decided to do some research.

What I found:

1. The only valid types for a C bitfield (at least for C89) are [unsigned|signed] int (as implied by Guy).

However, supposedly "many" C compilers allow other types.
Given that AFAIK we've not had any complaints about the use of
guint8 & etc as a bitfield type, presumably the compilers commonly used to compile Wireshark accept same.


2. I found the following to be interesting (although somewhat academic since with respect to portability (unsigned|signed) int are probably the only valid bitfield types which should be used).

I did some tests using VC9 (on Windows 32bit) and GCC 4.6.1 (on Fedora 32bit).

For these compilers apparently the type of a bitfield (for whatever the compiler accepts as a bitfield type) determines the bitfield alignment and the size of the struct containing that bitfield.

For example: Given
   struct radiotap_override {
      guint8 field;
      guint align:4, size:4;
   } aaa;

   struct radiotap_override {
      guint8 field;
      guint8 align:4, size:4;
   } bbb;

It turns out that:
 sizeof(aaa) = 8
 sizeof(bbb) = 2

Apparently the alignment of the start of the bitfield depends upon the (largest ?) bitfield type;

Also: Given:

   struct {
      guint16 a:12;
      guint16 b:12
   } xxx;

   struct {
      guint a:12;
      guint b:12
   } yyy;

The size of the two structs is the same, but the alignment of 'b' is different for each;

As I said: Interesting (in a minor way)  :)


Bill