C/C++:内存对齐(struct/union/field) 
原因 
? 字节对齐主要是为了提高内存的访问效率。  
 
对齐原则 
-  
首个成员在与结构体变量偏移量为0的地址处   -  
各成员变量在存放的时候根据在结构中出现的顺序依次申请空间   -  
变量对齐数 = Min(编译器默认对齐数,该成员大小)   -  
各成员变量对齐到自身对齐数的整数倍(嵌套结构体对齐到自身最大对齐数整数倍)   -  
结构体总大小为所有最大对齐数(包含嵌套结构体的成员对齐数)的整数倍        
示例 
1.不同顺序排列 
? S1大小:12字节(1+3 +4 + 1+3);  
? S2大小:8字节(1+1+2 + 4);  
? 粗体为对齐填充字节。  
struct S1
{
    char c1;
    int i;
    char c2;
};
struct S2
{
 	char c2;
    char c1;
    int i;
};
  
2.包含数组 
? student大小:24(10+2+4+1+3+4)  
? char name[10] 的本质是 10 个 char 变量,所以就把它当成 10 个 char 变量看就行了;  
? 粗体为对齐填充字节。  
struct student
{
	char name[10];
	int age;
	char sex;
	float score;
};
  
3.结构体嵌套 
? student大小:32(4+13+7+8)  
? st1大小:48(4+4+32+1+7)  
struct student
{
	int num;
	char name[13];
	double gender;
};
struct st1
{
	int age;
	struct student s1;
	char sex;
};
  
4.联合体嵌套 
? 联合体对齐方式要适合其中所有的成员(整个大小为最大对齐数的整数倍)  
? MyUnion大小:16(13+3)  
? st1大小:32(4+4+16+1+7),union1应按成员最大字节对齐数(8)对齐,整个结构体为double倍数  
union MyUnion
{
	int num;
	char name[13];
	double gender;
};
struct st1
{
	int age;
	union MyUnion union1;
	char sex;
};
  
pragma指令 
- 使用伪指令#pragma pack (n),C编译器将按照**min(n, sizeof(a))**个字节对齐(a为某类型变量,n= 1,2,4,8,16)。
 - 使用伪指令#pragma pack (),取消自定义字节对齐方式。
   
示例 
1.S1大小:6(1+1+4)  
? S2大小:10(1+1+6+2),嵌套时按照min(2,sizeof(a))对齐  
#pragma pack(2)
struct S1 {
	char a;
	long b;
};
struct S2 {
	char c;
	struct S1 d;
	char e;
};
#pragma pack()
  
2.S1大小:8(1+3+4)  
? S2大小:16(1+3+8+1+3),嵌套时按照min(8,sizeof(a))对齐  
#pragma pack(8)
struct S1 {
	char a;
	long b;
};
struct S2 {
	char c;
	struct S1 d;
	char e;
};
#pragma pack()
  
位域 
位域的声明和结构是类似的,有两个不同:  
 
示例 
? 连续相同类型可使用位域来节省空间(S1)  
? 连续不同类型需按照对齐规则分配空间(S2)  
? 含位域的结构体嵌套对齐规则与普通嵌套相同(S3)  
struct S1 {
	int i:8;
	int b:4;
	char a:3;
	double c;
};//16字节
struct S2 {
	int i:8;
	char a:3;
	int b : 4;
	double c;
};//24字节
struct S3 {
	char c;
	struct S2 d;
	char e;
};// 40字节
 
                
                
                
        
        
    
  
 
 |