当前位置:网站首页>Calculation of structure size (structure memory alignment)

Calculation of structure size (structure memory alignment)

2022-07-23 19:31:00 ... running snail ~

Preface

Have studied C We know the language , Integer variables have their own size , Floating point variables have their own size , Arrays also have their own size , So does the structure have its own size ?

The answer is yes , The structure also has its own size , however The size of a structure is not simply the sum of the sizes of each structure member . below , Let's talk about how to calculate the size of the structure .

Structure memory alignment rules

The size calculation of the structure follows the alignment rules of the structure :

  • The first member is offset from the structure variable by 0 The address of .( That is, the first address of the structure , That is, align to 0 It's about )
  • Other member variables are aligned to a number ( Align numbers ) An integral multiple of the address of .
  • The total size of the structure is the maximum number of alignments ( Each member variable has an alignment number ) Integer multiple .
  • If a structure is nested , The nested structure is aligned to an integral multiple of its maximum alignment , The overall size of the structure is the maximum number of alignments ( The number of alignments with nested structures ) Integer multiple .

Align numbers = The size of the structure member variable itself is smaller than the compiler's default alignment number .

notes :VS The default number of alignments in is 8, Not all compilers have a default alignment number , When the compiler has no default alignment number , The size of the member variable is the number of alignments of the member .


Calculation of structure size

You know the structure memory alignment rules , We can calculate the size of the structure . Calculating the size of the structure can be divided into three steps . Let's take the following structure as an example :

struct S
{
    
	double a;
	char b;
	int c;
};

First step : Find out the size of each member variable and compare it with the default alignment number of the compiler , Take the smaller value as the alignment number of the member variable .
 Insert picture description here
notes :VS The compiler default alignment number is 8.

The second step : Draw their relative positions in memory according to the corresponding alignment number of each member .
 Insert picture description here

The third step : The final size of the structure is determined by the maximum number of alignments .

Through the figure, we can know , The green part (double d Members occupy )+ The red part (char c Members occupy )+ Purple part (int i Members occupy )+ The white part between red and purple ( Wasted ) In total 16 Bytes of memory space .

We need to put the total memory space they occupy (16) The maximum number of alignments with structure members (8) Comparison , The total size of the structure is an integral multiple of the maximum alignment number , here 16 Is precisely 8 Integer multiple , So the structure is in VS The size under the compiler is 16 Bytes . That is, create a structural variable of this type , Memory needs to be opened up 16 Bytes of memory space .

Be careful : Most of the time , The total number of bytes that a member variable has occupied is not necessarily an integer multiple of the maximum number of alignments in its member variable , At this time, we need to expand it to an integer multiple of the maximum alignment number .

Why is there memory alignment ?

  • Platform reasons ( Reasons for transplantation ): Not all hardware platforms can access any data on any address ; Some platforms can only get certain types of data at certain addresses , Otherwise, a hardware exception will be thrown .
    such as , When a platform wants to get an integer data, it can only be at the address 4 The position of the multiple of , Then memory alignment is required , Otherwise, the integer data cannot be accessed .

  • Performance reasons : data structure ( Especially stacks ) It should be aligned on the natural boundary as much as possible . The reason lies in , To access unaligned memory , The processor needs to make two memory accesses ; Aligned memory access takes only one time .

Memory is so important , How can memory be wasted during memory alignment ?
Now it seems , In fact, the structure Memory alignment is the practice of trading space for time .

Skills in designing structures

In fact, when we design the structure , If the order of structure members is designed reasonably , It can avoid unnecessary memory consumption .
The member variables of the two structures are the same , But the order of member variables is different , There may be different sizes of structures :

struct S1
{
    
	char a;
	char b;
	int c;
};// Structure 1
struct S2
{
    
	char a;
	int c;
	char b;
};// Structure 2

 Insert picture description here

We can see , Structure 1 And the structure 2 The members are as like as two peas. , But when we calculate the size of two structures according to the memory alignment rules , You will find that the two structures are not the same size , stay VS The size of the first structure under the compiler is 8, The size of the second structure is 12.

You can see , The order of structure member variables is different , It may cause unnecessary loss of memory . Try to gather members with small space together , It can effectively avoid unnecessary waste of memory .

Change the default alignment number

To modify the default alignment number of the compiler , We need to use the following preprocessing commands :

#pragma pack()

If you put a number in parentheses of the preprocessing command , Then the default alignment number will be changed to the corresponding number ; If you only use this preprocessing command , Do not fill in numbers in parentheses , Then it will revert to the compiler's default alignment number .

#include <stdio.h>

#pragma pack(4)// Set the default alignment number to 4
struct S1
{
    
	char a;//1/4->1
	int b;//4/4->4
	char c;//1/4->1
};//12
#pragma pack()// Unset the default number of alignments , Restore to default 

#pragma pack(1)// Set the default alignment number to 1
struct S2
{
    
	char a;//1/1->1
	int b;//4/1->1
	char c;//1/1->1
};//6
#pragma pack()// Unset the default number of alignments , Restore to default 

int main()
{
    
	printf("%d\n", sizeof(struct S1));// The result is 12
	printf("%d\n", sizeof(struct S2));// The result is 6
	return 0;
}

therefore , When the alignment of the structure is not appropriate , We can change the default alignment number ourselves .

原网站

版权声明
本文为[... running snail ~]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/204/202207231737010857.html