[C language] Memory alignment of structures

1. Structure memory alignment rules


1. The first member is at an address with an offset of 0 from the structure variable.
2. Other member variables must be aligned to an address (offset) that is an integer multiple of a certain number (alignment number). The gcc compiler does not have a default alignment number. The member size is the alignment number
. The alignment number = a smaller value between the compiler's default alignment number (VS defaults to 8) and the member size. 3. The
total size of the structure is the maximum alignment number (each member variable has an integer multiple of the alignment number)
4. If the structure is nested, the nested structure is aligned to an integer multiple of its own maximum alignment number, and the overall size of the structure is the maximum alignment number of all (including nested structures) an integer multiple of the alignment number of the body)


See the following code:

struct S1//结构体变量
{
    
    
	char c1;//1 c1 第一个成员
	int a;//4   4<8 对齐数为4  此时4为该结构体的最大对齐数
	char c2;//1 对齐数为1
};
struct S2
{
    
    
	char c1;//1
	char c2;//1
	int a;//4
};
#include<stdio.h>
int main()
{
    
    
	struct S1 s1 = {
    
     0 };
	printf("%d\n", sizeof(s1));
	struct S2 s2 = {
    
     0 };
	printf("%d\n", sizeof(s2));
	return 0;
}

operation result:

12
8

Explanation (taking S1 as an example):

  • 1. The first member is at the address offset 0 from the structure variable. c1 in the code is the first member, and c1 occupies 1 byte, so c1 is stored in the blue part of the figure below

  • 2. Other member variables should be aligned to the address (offset) that is an integer multiple of a certain number (alignment number). The gcc compiler does not have a default alignment number. The member size is the alignment number.
    Alignment number = a smaller value between the compiler's default alignment number (VS defaults to 8) and the size of the member.
    I'm using VS, so the default alignment number is 8. The size of the second member c2 is 4, 4<8, so the alignment number of c2 is 4, so c2 starts to store the number that is a multiple of offset 4, because no number has been stored after the offset 4, so c2 starts to be stored at offset 4, and c2 occupies 4 bytes, so c2 is stored in the green part of the figure below

  • In the same way, c3 is stored in the orange part of the picture below

  • 3. The total size of the structure is an integer multiple of the maximum alignment number (each member variable has an alignment number). After storing c1 c2 c3 according to the rules, it should occupy a total of 1+4+1=6 bytes, but the result is 12. Because according to the first three alignment rules, the white part must be empty. According to this alignment rule, because c2 has the largest size, which is 4, the maximum alignment number of S1 is 4. After storing according to the first three alignment rules, add The upper blank part is 9, and the closest multiple of 4 is 12, so three more blank parts should be added, that is, the yellow part

  • Insert image description here

  • To sum up, the size of structure S1 is 12

  • Through the calculation results, we found that just by changing the positions of c1 and a, the size of the structure changed from 12 to 8, so we should keep the members with small spaces together as much as possible


  • 4. If a structure is nested and the nested structure is aligned to an integer multiple of its own maximum alignment number, the overall size of the structure is an integer of all maximum alignment numbers (including the alignment number of nested structures) Times
    see code:
struct S3
{
    
    
	double d;//8
	char c;//1
	int i;//4
};
struct S4
{
    
    
	char c1;//1
	struct S3 s3;//16 最大对齐数为8 从偏移量为8的时候开始
	double d;//8
};
#include<stdio.h>
int main()
{
    
    
	struct S3 s3 = {
    
     0 };
	printf("%d\n", sizeof(s3));
	struct S4 s4 = {
    
     0 };
	printf("%d\n", sizeof(s4));
	return 0;
}

Operation result:

16
32

explain:

  • According to the alignment rules, the size of S3 can be found to be 16
  • When calculating the S4 size, 16>8, so the alignment number is 8
  • The size of S4 can be calculated similarly to 32

2. Why does memory alignment exist?

  • 1. Platform reasons (transplantation reasons): Not all hardware platforms can access any data at any address; some hardware platforms can only obtain certain types of data at certain addresses, otherwise a hardware exception 2 will be thrown
    . .Performance reasons: Data structures (especially stacks) should be aligned on natural boundaries whenever possible. The reason is that in order to access unaligned memory, the processor needs to make two memory accesses; aligned memory access only requires one access.
    Generally speaking, the memory alignment of structures is to trade space for time.
  • So how to achieve alignment while saving space when designing a structure?
    1. Members with small spaces should be gathered together as much as possible
    2. Modify the default alignment number #pragma, which is generally a power of 2

Guess you like

Origin blog.csdn.net/m0_74102736/article/details/130451808