16

So I recently came across something like this

unsigned char ch : 7; 

inside a struct. I read about it a little. Apparently these are called bit fields. They are used to set the width of data that a char can receive. But how do we use these things. For example, I know that we can set variable ch to be a byte

unsigned char ch = 0x61; cout << ch << endl; 

This will output

a 

However, what do we do with the bitfields?

unsigned char ch : 7; ch = 0x61; //This doesn't work for some reason unsigned char ch : 7; unsigned char ch = 0x61; //Neither does this. 

Thanks for the help

3
  • 2
    Bitfields only work inside of class, struct, and union types. Commented Mar 8, 2016 at 1:11
  • 1
    en.cppreference.com/w/cpp/language/bit_field Commented Mar 8, 2016 at 1:12
  • I see. But how can they be used from withing a struct. what can they do? Commented Mar 8, 2016 at 1:12

1 Answer 1

31

Bitfields can only be used inside structured data types, i.e. struct, class, and union types. The purpose is to allow you to pack multiple members inside a single byte, without having to write lots of explicit shifts and masks. For instance, you can write:

struct halfbyte_t { unsigned int half1: 4; unsigned int half2: 4; } halfbyte; 

This declares a variable named halfbyte that contains two 4-bit members, which will be packed into a single 8-bit byte, rather than having to use 2 bytes if you just declared them unsigned char.

You access them just like any other structure member:

halfbyte.half1 = 3; cout << halfbyte.half3; 

1-bit fields are especially useful if you have lots of boolean flags in a structure, since you don't have to have a separate byte for each flag.

struct flag_t { unsigned int flag1: 1; unsigned int flag2: 1; unsigned int flag3: 1; unsigned int flag4: 1; ... }; 
Sign up to request clarification or add additional context in comments.

7 Comments

Thanks. that was a good explanation. I have a follow-up question though. When you said that the two halfbytes could be packed into an 8-bit character, How exactly would I do that?
@Q_A The most portable and semantically correct would be with arithmetic, e.g. (half1 << 4) | half2 or the other way around. You could hack it with unions or reinterpret casts, but the results won't always be consistent. See also stackoverflow.com/questions/19376426/…. The main usage is for saving space in memory constrained environments. If you find you often need to combine their values then you might reconsider using bit fields; really they're for things that are semantically separate.
The layout of bit-fields is non-portable, so they are of limited use if you are trying to write portable code
@M.M that's a sweeping statement and more FUD sans an explanation of "limited": code can portably use them for the functionality described in this answer, they're just not portable usable in raw binary I/O - but the same can be said of e.g. int due to endianness and the variety of encodings (sign magnitude, 2s complement...).
Do people use bit fields of size 1 for individual flags? That is, instead of defining, say, 16 const unsigned ints and performing the typical bit manipulation and testing algebra, I define a struct with 16 bit fields and use them like normal members, essentially? (I think I never need to test for "none set" in my use case.)
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.