Thursday, 17 May 2012

Bit Masks in C

Bit masks are where you specify the number of bits to use in a integral member of a class or struct. C has more restrictions than C++ on this. In particular, only "int", "signed int" or "unsigned int" can have bit masks in C. Many C compilers ignore bit masks altogether.
First rule of bit masks: Don't. Don't unless you have a really bad need to save a tiny amount of memory, and slowing down your code a lot isn't a problem (the compiler will have to work around things as they are not properly aligned). Bit masks are also inherently non-portable and differ on different compilers on different machines. Some compilers will ignore them totally.
If you really want to go ahead with it, all you do is put a colon after the member followed by the number of bits it should occupy. Here's an example:

struct TwelveHourTime
{
   unsigned hour     : 4;     //4 bits (16), enough for 1-12
   unsigned minute   : 6;     //6 bits (64), enough for 0-59
   unsigned am       : 1;     //1 bit, on for am off for pm
};

//   0 1 2 3 4 5 6 7 8 9 A
//  |_ _ _ _|_ _ _ _ _ _|_|
//    hour     minute    am 

You can use bit masks with a blank identifier to add some padding:

struct TwelveHourTime
{
   unsigned hour     : 4;     //4 bits (16), enough for 1-12
   unsigned minute   : 6;     //6 bits (64), enough for 0-59
   unsigned          : 5;     //5 unused bits
   unsigned am       : 1;     //1 bit, on for am off for pm
};

//   0 1 2 3 4 5 6 7 8 9 A B C D E F
//  |_ _ _ _|_ _ _ _ _ _|_ _ _ _ _|_|
//    hour     minute    (unused)  am 

You can a blank identifier with bit mask of 0 to force the next element to align to the boundary of the given type:

struct TwelveHourTime
{
   unsigned hour     : 4;     //4 bits (16), enough for 1-12
   char              : 0;     //push minute to the next byte boundary
   unsigned minute   : 6;     //6 bits (64), enough for 0-59
   unsigned am       : 1;     //1 bit, on for am off for pm
};

//   0 1 2 3 4 5 6 7 8 9 A B C D E
//  |_ _ _ _|_ _ _ _|_ _ _ _ _ _|_|
//    hour  (unused)  minute     am

Again, bit masks are very non-portable and the exact layout depends on the compiler and platform. The diagrams are a guide only.

No comments:

Post a Comment