Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bit setting question

In C or C++, it's apparently possible to restrict the number of bits a variable has, so for example:

unsigned char A:1;
unsigned char B:3;

I am unfamiliar however with how it works specifically, so a number of questions:

If I have a class with the following variables:

unsigned char A:1;
unsigned char B:3;
unsigned char C:1;
unsigned char D:3;
  1. What is the above technique actually called?
  2. Is above class four bytes in size, or one byte in size?
  3. Are the variables treated as 1 (or 3) bits as shown, or as per the 'unsigned char', treated as a byte each?
  4. Is there someway of combining the bits to a centralised byte? So for example:

.

unsigned char MainByte;
unsigned char A:1; //Can this be made to point at the first bit in MainByte?
unsigned char B:3; //Etc etc
unsigned char C:1;
unsigned char D:3;
  1. Is there an article that covers this topic in more depth?
  2. If 'A:1' is treated like an entire byte, what is the point/purple of it?

Feel free to mention any other considerations (like compiler restrictions or other limitations).

Thank you.

like image 858
SSight3 Avatar asked Sep 02 '11 22:09

SSight3


1 Answers

What is the above technique actually called?

Bitfields. And you're only supposed to use int (signed, unsigned or otherwise) as the "type", not char.

Is above class four bytes in size, or one byte in size?

Neither. It is probably sizeof(int) because the compiler generates a word-sized object. The actual bitfields will be stored within a byte, however. It'll just waste some space.

Are the variables treated as 1 (or 3) bits as shown, or as per the 'unsigned char', treated as a byte each?

They represent only the bits specified, and will be packed as tightly as possible.

Is there someway of combining the bits to a centralised byte? So for example:

Use a union:

struct bits {
  unsigned A:1;
  unsigned B:3;
  unsigned C:1;
  unsigned D:3;
};

union SplitByte {
  struct bits Bits;
  unsigned char Byte[sizeof(struct bits)];
  /* the array is a trick so the two fields
     are guaranteed to be the same size and
     thus be aligned on the same boundary */
} SplitByteObj;

// access the byte
SplitByteObj.Byte[0]

// access a bitfield
SplitByteObj.Bits.B

Note that there are problems with bitfields, for example when using threads. Each bitfield cannot be accessed individually, so you may get errors if you try to use a mutex to guard each of them. Also, the order in which the fields are laid out is not clearly specified by the standard. Many people prefer to use bitwise operators to implement bitfields manually for that reason.

Is there an article that covers this topic in more depth?

Not many. The first few you'll get when you Google it are about all you'll find. They're not a widely used construct. You'll be best off nitpicking the standard to figure out exactly how they work so that you don't get bitten by a weird edge case. I couldn't tell you exactly where in the standard they're specified.

If 'A:1' is treated like an entire byte, what is the point/purple of it?

It's not, but I've addressed this already.

like image 53
Chris Lutz Avatar answered Oct 12 '22 23:10

Chris Lutz