联合体和结构体对齐

字节对齐主要是为了提高内存的访问效率,比如intel 32为cpu,每个总线周期都是从偶地址开始读取32位的内存数据,如果数据存放地址不是从偶数开始,则可能出现需要两个总线周期才能读取到想要的数据,因此需要在内存中存放数据时进行对齐。

内存对齐主要遵循下面三个原则:
结构体变量的起始地址能够被其最宽的成员大小整除
结构体每个成员相对于起始地址的偏移能够被其自身大小整除,如果不能则在前一个成员后面补充字节
结构体总体大小能够被最宽的成员的大小整除,如不能则在后面补充字节

1、联合体同一时间只能存储1个被选择的变量,对其他成员变量赋值会覆盖原变量
2、联合体大小要至少能容纳最大的成员变量
3、联合体和结构体大小要是所有成员变量类型大小的整数倍

实例1

#include <iostream>

typedef union UNI
{
    char data1;
    unsigned short data2;
    double data3;
    char data4[30];   // 成员最大的占地址空间为30,但是需要满足double的8字节对齐,故需要补2个空位,为32字节大小。
    int data5; 
}MYUNI;         

typedef struct STU
{
    char data1;           // 1
    unsigned short data2;    // (1 + 1) + 2,1字节不满足unsighed short对齐,补1个空位。
    double data3;             // ((1 + 1) + 2 + 4) + 8,(1 + 1) + 2 = 4字节不满足double对齐,补4个空位。
    MYUNI uni;        //  ((1 + 1) + 2 + 4) + 8 + 32
    char data4[3];    // 48 +3,  48字节满足字节对齐,直接加3。(如果后面已经没有数据了,则需要满足最终的8字节对齐,补5个空位。)
    int data5;       // 51 + 4,最终需要满足double的8字节对齐,需要补空位1个成56.
}MYSTU;

int main()
{
    std::cout << sizeof(double) << std::endl;
    std::cout << "MYUNI:" << sizeof(MYUNI) << " MYSTU:" <<sizeof(MYSTU) << std::endl;

    while(1);

    return 0;
}


实例2:

typedef union u
{  
    char a;
    int b[5];
    double c;
    int d[3];     
}U;  
typedef struct s    
{     
    int  e;    
    double f;       
    short g;            
    U h;          
    char i[2]; 
}S;   

U大小至少要容纳最大的b[5]=4*5=20字节,同时要是变量类型最大值得整数倍,即sizeof(double)=8的整数倍,所有sizeof(U)=24
s的大小计算需要看上一篇关于结构体大小的计算的文章sizeof计算结构体大小,联合体的自身对齐值为成员变量的最大对齐值,也就double的自身对齐值8,所以s得大小为4+4(对齐满足8的倍数)+8+2+6(对齐满足8的倍数)+24+2+6(对齐满足8的倍数)=56

实例3

typedef union UNI
{
    int data;
    int data2[5];
    double data3;
}nu;    // 24

typedef struct STU
{
    int data;
    nu num;
    double data3;
}stu1;

std::cout << sizeof(stu1) << std::endl;   // 4 + 4(对齐double8长度的补充) + 24(如果不是8的倍数则需要增加长度满足) + 8

猜你喜欢

转载自blog.csdn.net/qq_23350817/article/details/89894757