C++ Bit Fields


Not too many people knows about C++ Bit Fields. It make decoding binary packet  effortless.

Link to article

Example: 

struct WeirdPacket
{
   unsigned int n1 : 1;
   unsigned int n2 : 7;
   unsigned int n3 : 7;
   unsigned int n4 : 17;
};

To decode:  

WeirdPacket w;   copy(w, buffer, 4); 

Then access your fields ip1.n1 to ip1.n4 at will.

Assumption:

copy also handles endian issue.

buffer points to the begin of weird packet.

Advertisements
C++ Bit Fields

4 thoughts on “C++ Bit Fields

  1. scaryreasoner says:

    Your code assumes an unsigned is 4 bytes — not always true.

    Why use bit fields to break it up into byte sized chunks when you can do the same thing by aliasing an unsigned char pointer to it and treating it as an array?

    eg:

    uint32_t x
    uint8_t *y = &x;

    Now you can refer to y[0] through y[3] to access the bytes of x.

    (Note, doing the reverse:

    char x[4];
    int *y = &x[0];

    *y = some_value;

    is not always cool, as x may not be aligned properly to be accessed as an int and some architectures (eg: ia64) really hate that, so to be safe for that kind of thing, either ensure alignment, or use memcpy().

    If you example used non-byte sized or non-byte aligned sets of bits it would make a bit more sense.

    However, even then, bitfields are not endian clean, so the same code means different things on big endian and little endian machines. On a big endian machine, your “n1” would be the high byte, on a little endian machine, n1 would be the low byte (or vice versa — I forget which way it goes, because I don’t every use bitfields — for exactly the reason that it’s different on different architectures.)

    If you want to use bitfields to access the bits within a single char, now that should be ok, and do the same thing on both big or little endian machines. Accessing more than 8 bits with a bit field isn’t portable though. I think “The C Programming Language” (don’t have my copy in front of me) mentions all these problems with bit fields.

    1. supertvo says:

      As to any technology, there are always pros and cons. If programmer can work around the endianness or simply deploy on one platform only, then it’s OK.

  2. supertvo says:

    Thank you for your inputs. My intent was to introduce the concept of bit parsing.

    I agree with you that using bit fields to break into byte-sized chunk is overkill and pointless. It’s just an example. I’ll change the example to make more sense.

    endian issue is solved easily. You can detect the platform and copy accordingly. Note that I use generic copy() function, not memcpy(), which handles endian.

    If you implement endian handling, it will be fine. We used it in both windows and linux.

    Alternatively, I did write GetBits/SetBits. I may post it soon.

  3. scaryreasoner says:

    If you use bit shifting and masking, you don’t even have to detect the endianness.

    For instance:

    uint8_t a, b, c, d;
    uint32_t x = a << 24 | b << 16 | c << 8 | d;

    works the same whether big or little endian.

    I’ve seen code like this:

    struct {
    #if BIG_ENDIAN
    int n1 : 8;
    int n2: 8
    int n3: 8;
    int n4: 8;
    #else
    int n4:8;
    int n3: 8;
    int n2: 8;
    int n1: 8;
    #endif;

    So, yeah, you can detect the endianness and handle it,but it’s freakin’ ugly.

    And, the C spec doesn’t even say how the bits are to be packed or aligned or ordered. Not only is it architecture dependent, it is *compiler* dependent.

    Your point may be to introduce bitfields. My point is bitfields are nearly always the worst way to do it in C, and are widely regarded as being a mistake in the design of the language, even by people who generally like the design of the language.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s