内存对齐

2019-12-19  本文已影响0人  CS_SDN

示例代码:


struct StudentOne {
        char a;         //1字节
        double b;       //8字节
        int c;          //4字节
        short d;        //2字节
    } MyStudent1;

    struct StudentTwo {
        double b;       //8字节
        char a;         //1字节
        short d;        //2字节
        int c;         //4字节
    } MyStudent2;
    NSLog(@"%lu---%lu--", sizeof(MyStudent1), sizeof(MyStudent2));

打印结果:24---16--
此时,相同的结构体,只是交换了变量 ab 在结构体中的顺序他们的大小就改变了

总结:内存对齐的原则:


1:数据成员对⻬规则:结构(struct)(或联合(union))的数据成员,第

一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要

从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,

结构体等)的整数倍开始(比如int为4字节,则要从4的整数倍地址开始存

储。

2:结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从

其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b

里有char,int ,double等元素,那b应该从8的整数倍开始存储.)

3:收尾工作:结构体的总大小,也就是sizeof的结果,.必须是其内部最大

成员的整数倍.不足的要补⻬。

MyStudent1 的进行对齐后结构为:

struct StudentOne { char a; // 1 byte char _pad0[7]; //补齐7字节成为8(随后跟着的 double 大小)的倍数,原则一 double b; // 8 bytes int c; // 4 bytes short d; // 2 byte char _pad1[2]; // 补齐2字节让结构体的大小成为最大成员大小double(8字节)的倍数,原则二 } MyStudent1;

验证结果,打印结构体:

long a = (long)&MyStudent1.a;  long b = (long)&MyStudent1.b ; long c = (long)&MyStudent1.c; long d = (long)&MyStudent1.d; NSLog(@"MyStudent1大小---%lu------", sizeof(MyStruct1)); NSLog(@“内存地址---%ld,%ld,%ld,%ld", a, b, c, d);

输出的结果为:MyStudent1大小—--24 ;内存地址---4539371424,4539371432,4539371440,4539371444。他们的内存占用符合内存对齐的规则。

char a + char _pad0[7] :    4539371424 // 占用 24-31

double b :                  4539371432 // 占用 32-39

int c :                    4539371440 // 占用 40-43

short d + char _pad1[2]:    4539371444 // 占用 44-47

通过上述规则进行对齐后的 MyStudent1 增加了 9 个字节变为 24 字节。而 MyStruct2 的所有数据成员和结构体本身只有 a 运用内存对齐的规则一增加了一个字节,所以大小为 16 字节。

为什么要进行内存对齐

内存对齐应该是编译器的管辖范围。编译器会为程序中的每个数据单元安排在适当的位置上,这个过程对于大部分程序员来说都应该是透明的。但如果你想了解更加底层的秘密,“内存对齐”就不应该对你透明了。

上一篇 下一篇

猜你喜欢

热点阅读