"Structure Alignment Rules in Memory" has many pictures and is easy to understand

Primer

Before understanding the structure alignment rules, let's look at an example
Example 1:

#include<iostream>
using namespace std;
struct Sut1
{
    
    
	char c;
	short st;
	int num;
}Sut1;
int main()
{
    
    
	cout << "sizeof(char) = " << sizeof(char) << endl;
	cout << "sizeof(short) = " << sizeof(short) << endl;
	cout << "sizeof(int) = " << sizeof(int) << endl;
	cout << "sizeof(Sut1) = " << sizeof(Sut1) << endl;
}

The output is as follows:
sizeof(char) = 1
sizeof(short) = 2
sizeof(int) = 4
sizeof(Sut1) = 8

The sum of the memory occupied by each element in the structure is 1+2+4=7, and the memory occupied by the structure itself is 8, which is not equal. So where does the extra byte of memory go?
After thinking about it carefully, there are two possibilities:

  1. The structure itself occupies 1 byte, and the sum of the memory occupied by the structure is its own 1 byte plus the sum of the bytes occupied by its elements
  2. How much memory a structure occupies is determined by some rule that we don't yet understand

Once you have an idea, you have to verify it. Let's verify the first idea first:

Let's define an empty structure to see if the memory it occupies is 1

#include<iostream>
using namespace std;
struct Sut1
{
    
    

}Sut1;
int main()
{
    
    
	cout << "sizeof(Sut1) = " << sizeof(Sut1) << endl;
}

In order to make the result more convincing, I use the running screenshot to prove that
insert image description here
the memory occupied by the structure itself is indeed 1 , which proves that the first idea is correct! ! !
Well, this is the end of this article, thank you for watching.

Just kidding, of course things are not that simple. This example can only prove that an empty structure occupies one byte, but it does not prove that the first idea is correct.
The proof failed... It’s okay, let’s do it again, and prove it in another way. Let’s look at the following example:
Example 2:

struct Sut1
{
    
    
	char c;
	int num;
	long long bigNum;
}Sut1;
int main()
{
    
    
	cout << "sizeof(long long) = " << sizeof(long long) << endl;
	cout << "sizeof(Sut1) = " << sizeof(Sut1) << endl;
}

Output:
sizeof(long long) = 8
sizeof(Sut1) = 16

If the first idea is correct, then sizeof(Sut1) = 1 of the structure itself + sizeof(char) +sizeof(int) + sizeof(long long) = 1+1+4+8 = 14, but the program runs The result is 16. This one counterexample is enough to prove the first idea wrong .

Then it can only be the second idea. Is the size of the memory occupied by the structure determined by certain rules? Yes, the alignment rules of structures in memory are described in detail below

Overview of storage rules for structures

Let's take a look first, which rules always make me confused about the size of the structure (see one by one)
specific rules:

  • Rule 1: The elements in the structure are put into the memory one by one in the defined order, but not in close arrangement. Starting from the first address stored in the structure, when each element is placed in the memory, it will think that the memory is divided by its own size, so the position where the element is placed must start at an integer multiple of the size of the space it occupies (Calculated with the first address of the structure variable being 0).
  • Rule 2: If a structure is nested within a structure, the members of the structure shall be stored from an address that is an integer multiple of the maximum element size inside the nested structure.
  • Rule 3: When the total size of the structure is finally calculated, that is, sizeof(Sut1), it must be an integer multiple of the largest member in it, and the deficiency must be filled.

It's normal not to understand these rules at the beginning. Here are some examples to explain each rule.

Application of Rules 1 and 3

We first use rule 1 to calculate the size of the structure in the previous example 1 and example 2.
Example 1 Example 2 Forgot? Then turn back to the top to see! What? Don't turn it over? Then... I'll move it down for you!

struct Sut1//例1
{
    
    
	char c;
	short st;
	int num;
}Sut1;
struct Sut2//例2
{
    
    
	char c;
	int num;
	long long bigNum;
}Sut2;

Let's analyze it first Sut1:

  • First, the system will charstore the type variable c in the 0th byte (that is, the first position in the memory of the structure)
  • Then, when storing shortthe deformation variable st, it will be stored in units of two bytes (because shortthe type occupies two bytes), because the first two-byte module already has data (c occupies 1 byte, and the other The byte does not store elements), so it will be stored in the second two-byte module, that is, stored in the 2~3 byte position , and the space that does not store data is the space wasted by aligning the structure elements.
  • Immediately after storing intthe variable num, since the occupied byte size is 4, it will be stored in units of 4 bytes, that is, it will find the first empty position that is an integer multiple of 4 and start storing. In this example, since the first 4-byte block is already occupied, num is stored in the second 4-byte block. That is, the 4~7 byte position

Sut2It is similar to Sut1the analysis process, I believe everyone can analyze it by themselves. Sut1And Sut2the storage diagram is as follows:
insert image description here

therefore:

  • The memory size occupied by Sut1 is 1 + 1 + 2 + 4 = 8
  • The memory size occupied by Sut2 is 1 + 3 + 4 + 8 = 16

Combining rule 1 and rule 3, let's look at the following example
example 3:

struct Sut3
{
    
    
	long long bigNum;
	char c;
	short st;
}Sut3;

If we only follow rule 1, we calculate sizeof(Sut3) = 8 + 1 + 1 + 2 = 12.
But its actual size is sizeof(Sut3) = 16. Because rule 3 stipulates that the final calculated size must be an integer multiple of the largest member in the structure, and the deficiency must be filled.
For this example, the largest member inside the structure is long longthe type, which is 8 bytes in size. 12 is not an integer multiple of 8, it needs to be completed, that is, 4 bytes should be filled, and the size of the structure becomes 16.
insert image description here

Let's look at a few more examples to strengthen our understanding of rules 1 and 3
Example 4 :

struct Sut4
{
    
    
	long long bigNum;
	char c;
	int num;
	short st;
}Sut4;
struct Sut5
{
    
    
	char c1;
	long long bigNum;
	char c2;
	short st;
}Sut5;
struct Sut6
{
    
    
	//注意,无论什么类型的指针,都只占4个字节
	int *p1;
	long long bigNum;
	char c;
	char *p2;
	short st;
}Sut6;

insert image description here

Sut6We analyze the most complex :

  • First, the system will int*store the type pointer variable p1 in units of 4 bytes (any type of pointer only occupies 4 bytes), and store it in the 0~3 byte space.
  • Then long longwhen storing the deformation variable bigNum, it will be stored in units of 8 bytes. Since the first 8-byte module already has data, it will be stored in the second 8-byte module, that is, stored in 8~ 15 bytes of space.
  • Immediately after storing charthe type variable c, it only occupies 1 byte, and it can be directly stored in the next byte space (the 16th byte space).
  • Then, when storing char*the shape pointer variable p2, it will be stored in units of 4 bytes. Since the first 5 4-byte modules already have data, it will be stored in the sixth 4-byte module, that is, stored in to 20~23 bytes of space.
  • When storing shortthe deformation variable st, it will be stored in units of 2 bytes, and stored in the 24~25 byte space.
  • In the end, it takes up 26 bytes of space (0~25), which is not long longan integer multiple of the largest member type, and needs to be filled to 32 bytes.

After these few examples, I believe that you have a thorough understanding of rules 1 and 3. Next, let's look at rule 2, how to understand the storage rules of nested structures in structures.

Application of Rule 2

Nesting a structure in a structure is a relatively complex structure that requires three rules to be used together. Let's look directly at Example
5:

struct Sut1
{
    
    
	short st;
	int num;
};
struct Sut2
{
    
    
	char c1;
	Sut1 sut1;
	char c2;
}Sut2;

According to the previous understanding, we can easily find sizeof(Sut1) = 8, so how to find sizeof(Sut2)? Take a look at rule 2 first:
If a structure (Sut1) is nested in a structure (Sut2), then Sut1 should start storing from an address that is an integer multiple of the maximum element size inside itself.

Now to Sut2analyze:

  • Store c1 in the 0 byte space.
  • The largest element in sut1 is intthe type num, which occupies 4 bytes, so sut1 should be stored at an address that is an integer multiple of 4, and because sut1 itself occupies 8 bytes of space, that is, in the space of 4~11 bytes.
  • Then c2 is immediately followed by storage in the 12th byte space. At this time, the structure occupies 13 byte spaces (0~12), and the elements have been stored. See if it needs to be completed. In Sut2 (of course including Sut1) The largest element is inta type, occupying 4 spaces, so it is filled to an integer multiple of 4 and 16 bytes of space

The storage diagram is as follows:
insert image description here
Next, let’s take an example of scalp numbness. After understanding this example, this part of the content is basically mastered.
Example 6:

struct Sut1
{
    
    
	char c;
	int num;
};
struct Sut2
{
    
    
	long long bigNum;
	int num;
};
struct Sut3
{
    
    
	int num;
	Sut1 sut1;
	double doub;
	Sut2 sut2;
	short st;
};

Obviously sizeof(Sut3) = 48. The analysis is not analyzed, and the previous rules are used to directly go to the picture:
insert image description here

optimal structure

Through the previous examples, we learned that the space occupied by the structure is not only related to the type and quantity of its internal elements, but also related to the arrangement order of different types of elements . Therefore, it is particularly important to properly sort the elements in the structure.
Optimal structure:
a structure that determines the type and quantity of elements and arranges its elements in a certain order takes up the smallest space, called the optimal structure

Next, we explain how to obtain the optimal structure through an example:
Example 7:

struct Sut
{
    
    
	char c;
	long long bigNum;
	int num;
	double doub;
	short st;
};

We can easily find sizeof(Sut) = 40 now. From the figure below, we found that a total of 7+4+6=17 bytes of space was wasted, nearly half of the space wasted! It hurts to look at it.
insert image description here
Let's try to optimize this structure into an optimal structure to see how much space we can save.
The optimization principle is very simple, the elements that occupy less memory are arranged first .
The optimal structure is as follows:

struct Sut
{
    
    
	char c;
	short st;
	int num;
	long long bigNum;
	double doub;
};

insert image description here

It only occupies 24 bytes of space! Save 16 spaces than before optimization!
At the same time, we also found that the optimal structure is not unique . For example, if long longthe type data and doubletype data are exchanged, the space it occupies is still 24, which is also the optimal structure.

Well, this article is really over here, your likes, comments, attention, and favorites are my greatest support, thank you!

Guess you like

Origin blog.csdn.net/qq_52324409/article/details/121434761