[Advanced C language] bit segment (structure case)

Tip: I suggest that you understand the calculation method of the structure size (structure memory alignment) before reading this blog post.

 ( The following code results are all tested in the VS2022 environment )

Introduction: The bit segment defines the space occupied by the member variables in the structure in units of bits. The bit segment structure can save space and facilitate operation.

 The difference between a bit field and a structure:

  1. The members of the bit segment can only be unsigned int, signed int, int, char type data
  2. The member name of a bit field must be followed by a colon and a number
  3. The unit of bit segment is bit, and the unit of structure is byte. Compared with structure, bit segment saves more space

 First, let's take a brief look at the difference between a structure and a bit segment:

 

​
struct Stu
{
	int a : 4;//这里的4,代表4个比特位,而不是字节!
	int b : 5;//5个比特位
	int c : 9;//9个比特位
	int d : 28;//28个比特位
};

 In the above code, a is 4 bits, b is 5 bits, c is 9 bits, and d is 28 bits, not bytes! ! ! (where one byte is equal to 8 bits... )

It is said in the introduction of the bit segment that the bit segment is more space-saving, so logically we might as well make a bold guess!

The above code uses a total of 46 bits, so can we think that it is OK to need a total of 6 bytes? ? ?

Then let's look at the running results:

The running results are different from what we guessed. In fact, the memory allocation of the bit segment is also regular. Next, we can study the memory allocation of the bit segment! ! !


Bit segment memory allocation:

1. The bit segment is spaced according to 4 bytes (int) or 1 byte (char) to open up space (32-bit system)

2. The bit segment is not cross-platform. Portable programs should avoid using the bit segment because it has many uncertain factors

To explain clause 2:

 

1. The way the bit segment is stored on different platforms is uncertain. For example, in the above code, the bit segment first opens up 4 bytes at a time (because it is of int type, not char type), int a: 4; int b :5; int c:9; Among them, a, b, and c occupy a total of 18 bits, leaving 14 bits, and the following int d:28; uses the remaining 14 bits first, It is uncertain whether to open up 4 bytes for storage or directly open up 4 bytes for storage (different platforms). In terms of storing data, if you store data in a byte (8 bits), it is also uncertain whether to store data from high to low or from low to high!

2. For example: the number of bytes occupied by the int type of C language is different between 16-bit and 32-bit microcontrollers. In the 32-bit system, it is 4 bytes (the editor uses a 32-bit system), and in the 16-bit system. It is 2 bytes, so in the int d:28; in the picture above, d occupies 28 bits (in 32 systems), if you take this program into a 16-bit system, it will go wrong! Because the int type has a total of only 2 bytes in a 16-bit system, that is, the maximum memory is 16 bits, and there are 28 bits here, it will definitely go wrong! So it also highlights a key point, that is, the allocated memory size cannot exceed the specified size!

3. Whether int is regarded as an unsigned number or a signed number is uncertain on different platforms!

When we are familiar with the above content, we can use some cases to calculate our (Vs2022 environment) memory allocation rules!

 case:

struct S
{
	char a : 3;
	char b : 4;
	char c : 5;
	char d : 4;
};
int main()
{
	struct S ss = { 0 };
	ss.a = 16;
	ss.b = 12;
	ss.c = 3;
	ss.d = 8;
	return 0;
}

 As we all know, the data in the computer is stored in binary form, and the memory window is displayed in hexadecimal in the Vs environment. Next, we will analyze step by step according to the process of the above code:

1. ss.a=16 The binary of 16 is 10000 ss.b=12 The binary of 12 is 1100 ss.c=3 The binary of 3 is 0011 ss.d=8 The binary of 8 is 1000

2. Because it is char type data, so the system will open up a byte first! Because we initialized to 0 at the beginning, the description is as follows:

 

3. Let's assume that the binary data is stored from low to high. The first data ss.a, because the first data is limited to 3 bits, so it can only be stored in 000, and the first byte is stored in the first There are 5 bits left after the first data, and the second data is ss.b which limits 4 bits, and the second byte can also be stored, so it is stored in 1100, as shown in the figure:

 4. When we store the third data, we find that the first byte is not enough, then we assume that the remaining bit is not used, and then open up another byte! When we store the third data ss.c, ss.c is limited to 5 bits, the stored data is 00011, and when we store the fourth data, we find that the second byte has 3 bits left, then According to the above results, we will open up another byte to store the fourth data. The fourth data is limited to four bits and stored in 1000, as shown in the figure:

 

 So we assume a total of 3 bytes are used! ! !

 5. When we assume such storage, the editor uses the VS2022 environment to test the results:

 operation result:

 Turns out our assumptions were exactly the same as the test results! ! !

Then we can use this method as a bit segment storage method in the VS environment. In this way, we understand the calculation method of the bit segment in the Vs compilation environment!

 

 Taking out the above code, we will find that 4 bytes are allocated at the beginning (int 32-bit system), and the integers a, b, and c occupy a total of 4 bytes, while d itself occupies 4 bytes. bytes! So the running result is 8! ! !


 The size calculation of the union of structure and bit field:

struct Stu
{
	char a : 4;
	char b : 3;
	int c;
	char d : 6 ;
};
int main()
{
	printf("%d\n", sizeof(struct Stu));
	return 0;
}

Analysis: The first two of the above are char type bit segment members, then open up a byte (the offset is 0 at this time) to store the first and second data (the bit segment does not need to consider alignment), and the third data is The structure member of int type can only be stored from the byte whose offset is 4. The fourth data is a bit segment member, so there is no need to consider byte alignment, so it is stored in the space with offset 8. So there are 9 bytes in total, but there are structure members in it, so the total byte size is calculated according to the memory alignment of the structure as a whole. The maximum alignment digit is 4, and 9 is not a multiple of 4, so it has been increased to 12! ! ! So the total number of bytes is 12.

 

operation result: 


Again! The calculation process of the editor's blog is all in the Vs compilation environment! ! ! The results of other platforms may not be accurate.......

Guess you like

Origin blog.csdn.net/m0_73968621/article/details/129072576