Detailed Explanation of Bit Fields in C Language

In embedded development, we often encounter code like this:

struct{unsigned int widthValidated : 1;unsigned int heightValidated : 1;} status;

What does this definition of a structure variable mean? The main reason is that some information only needs to occupy a few or a single binary bit when stored, and does not require a full byte. For example, when storing a switch state, there are only two states, 0 and 1, which can be represented with one bit. To save storage space and simplify processing, C language provides a data structure called “bit field”.Bit fields: They divide the bits in a byte into several different areas and specify the number of bits for each area. Each field has a field name, allowing operations in the program by field name. This way, several different objects can be represented using the binary bits of one byte. The definition of a bit field is similar to that of a structure, and its form is:

struct BitFieldStructureName {    BitFieldList};

The form of the bit field list is:

type [member_name] : width;

Below is a description of the variable elements in a bit field:Detailed Explanation of Bit Fields in C Language The usage of bit fields is the same as that of structure members, and its general form is:

bitFieldVariableName.bitFieldName bitFieldVariableName->bitFieldName

The greatest advantage of bit fields is to save storage space; essentially, it is a type of structure, but its members are allocated by bits. For example, in the following case:

#include<stdio.h>#include<string.h>
/* Define a simple structure */struct{unsigned int widthValidated;unsigned int heightValidated;} status1;
/* Define a bit field structure */struct{unsigned int widthValidated : 1;unsigned int heightValidated : 1;} status2;
int main( ){printf( "Memory size occupied by status1 : %ld\n", sizeof(status1));printf( "Memory size occupied by status2 : %ld\n", sizeof(status2));
return 0;}

When the code is compiled and executed, it produces the following results:

Memory size occupied by status1 : 8Memory size occupied by status2 : 4

The structure status1 consists of two normal unsigned int type variables, occupying 8 bytes of memory, while the structure status2 also consists of unsigned int type variables, but it only uses the first 2 bits of one unsigned int type memory, leaving 30 bits unused, thus occupying 4 bytes of memory. The following points explain the definition of bit fields:1. A bit field is stored in the same byte; if there is not enough space left in a byte to store another bit field, it will start storing that bit field from the next unit. A bit field can also intentionally start from the next unit. For example:

struct bs{unsigned a:4;unsigned  :4;   /* Empty field */unsigned b:4;   /* Starts storing from the next unit */unsigned c:4;}

In this bit field definition, a occupies 4 bits of the first byte, the next 4 bits are filled with 0 to indicate unused, b starts from the second byte, occupying 4 bits, and c occupies 4 bits.2. The width of a bit field cannot exceed the length of the data type it is attached to; member variables are all typed, and this type limits the maximum length of the member variable, so the number after the colon cannot exceed this length.3. Bit fields can be unnamed; in this case, they are only used for padding or adjusting positions. Unnamed bit fields cannot be used. For example:

struct k{int a:1;int  :2;    /* These 2 bits cannot be used */int b:3;int c:2;};

4. When adjacent members have the same type, if their bit widths sum to less than the sizeof the type, the subsequent members are stored next to the previous member until they cannot fit; if their bit widths sum to more than the sizeof the type, the subsequent members will start from a new storage unit, with an offset that is a multiple of the type size. For example:

#include<stdio.h>
int main(){struct bs{unsigned m: 6;unsigned n: 12;unsigned p: 4;};
printf("%ld\n", sizeof(struct bs));
return 0;}

The result of running this is:

4

The types of m, n, and p are all unsigned int, and the result of sizeof is 4 bytes (Byte), which is 32 bits (Bit). The sum of the bit widths of m, n, and p is 6+12+4 = 22, which is less than 32, so they will be stored next to each other without gaps.5. When adjacent members have different types, different compilers have different implementation schemes; GCC will compress storage, while VC/VS will not. For example:

#include<stdio.h>
int main(){struct bs{unsigned m: 12;unsigned char ch: 4;unsigned p: 4;};
printf("%ld\n", sizeof(struct bs));
return 0;}

The result under GCC is 4, with the three members stored next to each other; under VC/VS, the result is 12, with the three members stored according to their respective types (similar to the storage method when the bit width is not specified).6. If there are non-bit field members interspersed between members, compression will not occur. For example:

struct bs{unsigned m: 12;unsigned ch;unsigned p: 4;};

The result of sizeof is 12 across all compilers. Note: Bit field members often do not occupy a complete byte and may not be at the beginning of a byte, so using & to get the address of a bit field member is meaningless, and C language prohibits this. Addresses are numbered by bytes (Byte), not by bits (bit). Through an example, we can deepen our understanding and application of bit fields:

#include<stdio.h><string.h>
struct{unsigned int age : 3;} Age;
int main( ){   Age.age = 4;printf( "Sizeof( Age ) : %d\n", sizeof(Age) );printf( "Age.age : %d\n", Age.age );
   Age.age = 7;printf( "Age.age : %d\n", Age.age );
   Age.age = 8; // Binary representation is 1000, exceeds printf( "Age.age : %d\n", Age.age );
return 0;}

When the above code is compiled, it will generate a warning, and when the above code is executed, it will produce the following results:

  1. Sizeof( Age ) : 4Age.age : 4Age.age : 7Age.age : 0
    

When executing Age.age = 8;, the binary representation is: 1000, which has four bits, exceeding the bit field, so a warning will be prompted.https://blog.csdn.net/m0_38106923/article/details/123298469

Leave a Comment