Some information does not need to occupy a complete byte, but only a few or a binary bit. For example, when storing a switch quantity, there are only 0 and 1 states, and a binary can be used.

In order to save storage space and simplify processing, C language provides a data structure called “bit field” or “bit segment”. The so-called “bit-field” divides the binary bits in a byte into several different regions, and states the number of bits in each region. Each domain has a domain name that allows you to operate by domain name in the program. This allows several different objects to be represented as a binary field of one byte.

1, define,

structBit-field structure name {Bit-field list};Copy the code

Form of bit-field list: Type specifier Bit domain name: bit-field length

Such as:

structbs 
{ 
    int a:8; 
    int b:2; 
    int c:6; 
}data;
Copy the code

Note: Data is bs variable, in which bit field A occupies 8 bits, bit field B occupies 2 bits, and bit field C occupies 6 bits. (8 bits per byte)

2. The bit domain can have no bit domain name

In this case, it is used only for filling or adjusting positions. Nameless bit fields are not used.

Such as:

typedef   structk 
{ 
    int  a:1 
    int  :2    
    int  b:3 
    int  c:2 
};
Copy the code

As you can see from the above analysis, a bitfield is essentially a type of structure, but its members are assigned in binary form.

3. Pointer type variables cannot specify the number of bits occupied

This is easy to understand. In C, all pointer types are 4 bytes and cannot be changed.

4, struct variable binary bits brief description

For example, define a structure as follows:

typedefstruct  test
{
    int           a:2;
    unsigned int  b:2;
};
Copy the code

For the test structure, both a and B members occupy two bits, but the maximum size of the storage is different. Where: A is signed, so the first digit is used to store symbols, representing the maximum value of binary “+1”, that is, 1; B is unsigned and represents a maximum of binary “11”, that is, 3. This structure occupies a size of 4 bytes, not 4 bits!

Remember: bit-field members cannot be sizeof individually, and when assigning a value to a bit-field variable member, it will automatically truncate if the value exceeds the sizeof the variable.

The main purpose of using bitfields is to compress storage, and the general rules are as follows:

  1. If adjacent bit-field fields are of the same type and the sum of their bitwidths is less than the sizeof the type, the following fields will be stored next to the previous one until it cannot accommodate them.
  2. If adjacent bit-field fields are of the same type, but the sum of their bitwidths is greater than sizeof the type, the following fields will start from the new storage unit and have an offset that is an integer multiple of their type size.

Example 1:

structBF1
{
    char f1 : 3;
    char f2 : 4;
    char f3 : 5;
};
Copy the code

Its memory layout is:

|__f1___|____f2___ |__|____f3______|______|
|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|
Copy the code

The bit-field type is char, and the first byte only holds F1 and F2, so F2 is compressed into the first byte and F3 only starts from the next byte. So sizeof BF1 is equal to 2.

  1. If the type of the adjacent bit-field field is different, the specific implementation varies from compiler to compiler, and VC6 takes the uncompressed approach

Dev-c ++ adopts compression mode;

Example 2:

structBF2
{	
    char f1 :  3;
    short f2 : 4;
    char f3 :  5;
};
Copy the code

Due to the different types of adjacent bitfields, its sizeof is 6 in VC6 and 2 in dev-C ++.

  1. If bit-field fields are interspersed with non-bit-field fields, no compression is performed.

Example 3:

structBF3
{
    char f1 : 3;
    char f2;
    char f3 : 5;
};
Copy the code

Non-bit-field fields are interwoven, do not compress, and have a size of 3 in both VC6 and Dev-C++.

We use these examples to illustrate that when defining bitfields, it is best to put all bitfields together to save space, and also to emphasize that bitfields are allocated in the order they are defined.

  1. The total size of the entire structure is an integer multiple of the size of the widest primitive type member!

Let’s look at an example, and you’ll be amazed:

struct  mybitfields
{
    unsigned short a : 4;
    unsigned short b : 5;
    unsigned short c : 7; } test; = >sizeof(test) ==2;

struct mybitfields
{
    unsigned char a : 4;
    unsigned char b : 5;
    unsigned char c : 7; } test; = >sizeof(test) ==3;

struct mybitfields
{
    unsigned char a : 4;
    unsigned short b : 5;
    unsigned char c : 7; } test; = >sizeof(test) ==6;

struct mybitfields
{
    unsigned short a : 4;
    unsigned char b : 5;
    unsigned char c : 7; } test; = >sizeof(test) ==4;

struct mybitfields
{
    unsigned char a : 4;
    unsigned char b : 5;
    unsigned short c : 7; } test; = >sizeof(test) ==4;

struct mybitfields
{
    unsigned char a : 4;
    unsigned int b : 5;
    unsigned short c : 7; } test; = >sizeof(test) ==12;
Copy the code

5. The number of bytes of common built-in types

For 32-bit compilers:

Char: 1 byte

Pointer variable: 4 bytes (32-bit addressing space is 2^32, which is 32 bits, which is 4 bytes. Same with 64-bit compilers.)

Short int: 2 bytes

Int: 4 bytes

Unsigned int :4 bytes

Float: 4 bytes

Double: 8 bytes

Long: 4 bytes

Long long: 8 bytes

Unsigned long:4 bytes