Structure Alignment - C Language

Structure

Basics of Structs
A structure is a collection of values ​​called member variables. Each member of the structure can be a variable of a different type.

declaration of the structure

struct tag // tag 结构体标签
{
    
    
	member - list; //成员列表

}variable - list; //变量列表  注意:这里的分号不能省略

special structure declaration

//匿名结构体类型
struct
{
    
    
	int a;
	char b;
	float c;
}x;

struct
{
    
    
	int a;
	char b;
	float c;
}a[20], * p;

struct self reference

struct Node
{
    
    
 int data;
 struct Node* next;
};

typedef struct Node
{
    
    
 int data;
 struct Node* next;
}Node;

Structure Alignment Rules

  1. The first member is at offset 0 from the structure variable.

  2. Other member variables should be aligned to addresses that are integer multiples of a certain number (alignment number).
    Alignment number = The smaller of the compiler's default alignment number and the size of the member.
    The default value in VS is 8.
    In the Linux environment, there is no default alignment number. At this time, its own size is the default alignment number.

  3. The total size of the structure is an integer multiple of the maximum alignment number (each member variable has an alignment number).

  4. If a structure is nested, the nested structure is aligned to an integer multiple of its own maximum alignment number, and the
    overall is an integer multiple of all the maximum alignment numbers (including the alignment number of nested structures) .

Example 1:

struct S1
{
    
    
	char c1; 
	int i;   
	char c2; 
};

Note: As shown in the figure below, it is assumed that one grid/unit is one byte.

The first structure member c1 is stored at the address offset 0 from the structure variable.

At this time, other member variables of the structure must be aligned to addresses that are integer multiples of the alignment number .

i is an int type with a size of 4 bytes. The default alignment value of VS is 8. The smaller value of 4 and 8 is 4, so i needs to be stored in the structure variable with a corresponding offset of 4 words. The address that is an integer multiple of the section.
c2 is a char type, which is 1 byte. The default alignment number is 8, and the smaller value is 1, so c2 needs to be stored at an address whose offset is an integer multiple of 1 byte in the structure variable. Here is Just store it backwards, because 9 is a multiple of 1.

Finally, the total size of the structure is an integer multiple of the maximum alignment number (each member variable has an alignment number).
The alignment number of c1 is 1,
the alignment number of i is 4,
the alignment number of c2 is 1

The maximum alignment among the three variables is 4, that is to say, the final size of the structure is an integer multiple of 4 bytes. 0 - 8 bytes have been used here, which is 9 bytes, so we need to continue to open up space backwards until the offset corresponding to the structure variable is at the 12-byte address, which is an integer multiple of 4, so In the end this code opens up 12 bytes of space.

Example 2:

struct S2
{
    
    
	char c1;  //char类型的大小是 1 字节   默认对齐数是8   1和8取其较小值 最终对齐数是1
	char c2;  //   同上
	int i;    //int 类型的大小是 4 字节   默认对齐数是8    4和8取其较小值 最终对齐数是4
};

Note: c1 is stored at an address with an offset of 0 from the structure variable.

c2 is stored in the structure variable at an address whose offset is an integer multiple of 1 byte.

i is stored at the address where the corresponding offset of the structure variable is an integer multiple of 4 bytes.

Finally, the total size of the structure is at addresses that are integer multiples of the maximum alignment number 4, and 0 - 7 use 8 bytes of space.

insert image description here

practise:

struct S3
{
    
    
	double d;
	char c;  
	int i;  
}; 

insert image description here

Example 3: Nested structures within structures

struct S3
{
    
    
	double d;
	char c;  
	int i;   
}; 
struct S4
{
    
    
	char c1; 
	struct S3; 
	double d; 
};

Here is the fourth rule of structure alignment:

If a structure is nested, the nested structure is aligned to an integer multiple of its maximum alignment number
(to explain this sentence, s3 is a nested structure, and its internal maximum alignment number is 8. Because the alignment number of d is 8, the alignment number of c is 1, and the alignment number of i is 4, whichever is the largest, then the alignment number of s3 is 8. At this time, the default alignment number of vs is 8, whichever of the two A smaller value, so the variable s3 is eventually stored at an offset that is an integer multiple of 8 bytes).

The overall size of the structure is an integer multiple of all maximum alignments (including the alignment of nested structures).

as the picture shows:
insert image description here

Specifically we can verify:

struct S1
{
    
    
	char c1; 
	int i;   
	char c2; 
};
struct S2
{
    
    
	char c1; 
	char c2; 
	int i;  
};
struct S3
{
    
    
	double d;
	char c;  
	int i;   
}; 
struct S4
{
    
    
	char c1; 
	struct S3 s3;  
	double d;
};
int main()
{
    
    
	printf("%d\n", sizeof(struct S1));
	printf("%d\n", sizeof(struct S2));
	printf("%d\n", sizeof(struct S3));
	printf("%d\n", sizeof(struct S4));
	return 0;
}

The output is:
insert image description here

We can also verify it through the library function offsetof, taking s3 as an example:
insert image description here
insert image description here
Note:
offestof: calculates the offset of the structure member relative to the starting position.
The return type is size_t
header file: <stddef.h>

Why does memory alignment exist?

Most of the reference materials say this:

  1. Platform reasons (transplantation reasons): Not all hardware platforms can access any data at any address; some hardware platforms can only fetch certain types of data at certain addresses, otherwise a hardware exception will be thrown.
  2. Performance reasons: Data structures (especially stacks) should be aligned on natural boundaries as much as possible. The reason is that to access unaligned memory, the processor needs to make two memory accesses; while aligned memory accesses require only one access.
    As shown in the figure:
    insert image description here
    Generally speaking:
    the memory alignment of the structure is the practice of exchanging space for time.

When designing the structure, we must not only satisfy the alignment, but also save space. How to do it:
let the members that occupy a small space be gathered together as much as possible

//例如:
struct S1
{
    
    
 char c1;
 int i;
 char c2;
};
struct S2
{
    
    
 char c1;
 char c2;
 int i;
};

The members of the S1 and S2 types are exactly the same, but there are some differences in the size of the space occupied by S1 and S2.

Modify the default alignment number
Here, we can also change our default alignment number through the #pragma preprocessing directive.
insert image description here
The above is for reference only, if there are any mistakes, please advise, thank you.

Guess you like

Origin blog.csdn.net/m0_73969113/article/details/130913532