Eric
Eric

Reputation: 19873

Using nibbles (4 bits variables) in windows C/C++

I'm programming network headers and a lot of protocols use 4 bits fields. Is there a convenient type I can use to represent this information?

The smallest type I've found is a BYTE. I must then use a lot of binary operations to reference only a few bits inside that variable.

Upvotes: 20

Views: 43620

Answers (5)

Mehrdad Afshari
Mehrdad Afshari

Reputation: 422172

Since the memory is byte-addressed, you can't address any unit smaller than a single byte. However, you can build the struct you want to send over the network and use bit fields like this:

struct A {
   unsigned int nibble1 : 4;
   unsigned int nibble2 : 4;
};

Upvotes: 38

D.Shawley
D.Shawley

Reputation: 59613

Everyone seems to like using bit-fields in structs 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.

Upvotes: 9

Christoffer
Christoffer

Reputation: 12910

Expanding on Mehrdads answer, also use a union with a byte in order to avoid some evil-looking casts:

union Nibbler {
     struct { 
        unsigned int first:4;
        unsigned int second:4;
     } nibbles;
     unsigned char byte_value;
}

Upvotes: 17

Jon-Eric
Jon-Eric

Reputation: 17295

Use fields in a struct:

struct Header
{
    unsigned int lowestNibble : 4;
    unsigned int anotherNibble : 4;
    unsigned int : 18;                 # Unnamed padding.
    bool aBool : 1;
    bool anotherBool : 1;
    unsigned int highestNibble : 4;
};

The : 4 indicates that entry should occupy 4 bits. You can use any number of bits you like. You can use any built in type you like.

Typically you end up casting a pointer to your data to a Header * then doing something like:

pHeader->lowestNibble = 5;

Upvotes: 4

Foredecker
Foredecker

Reputation: 7491

No, there are no convenient types for nibbles. But, its easy to make them with macros or with template functions. This works well espeicaly if/when you need to deal with endian-ness.

Foredecker

Upvotes: -3

Related Questions