结构体内存对齐

对象内存对齐

探讨的问题

1.什么是内存对齐?
2.为什么要做内存对齐?
3.结构体内存对齐规则
4.源码内存对齐算法

一.什么是内存对齐?

计算机内存都是以字节为单位划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但是实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k(通常它为4或8的倍数),这就是所谓的内存对齐。内存对齐是一种在计算机内存中排列数据(表现为变量的地址) 、访问数据(表现为CPU读取数据)的一种方式。
内存对齐包含了两种相互独立又相互关联的部分:基本数据对齐和结构体数据对齐 。

二.为什么要做内存对齐?

1.平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2.性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

三.结构体内存对齐规则

当我们定义一个 struct 的时候,它在内存中是怎么存储的?占用了多少字节的内存空间呢?

//1、定义两个结构体
struct Mystruct1{
    char a;     //1字节
    double b;   //8字节
    int c;      //4字节
    short d;    //2字节
}Mystruct1;

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

//计算 结构体占用的内存大小
NSLog(@"%lu-%lu",sizeof(Mystruct1),sizeof(Mystruct2));

输出 24-16

从打印结果看出一个问题,结构体中变量相同,只是顺序不同,结果影响结构体占用内存大小,这就是iOS中内存对齐

内存对齐规则

1.数据成员对⻬规则:结构(struct)(或联合(union))的数据成员,第
一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要
从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,
结构体等)的整数倍开始(比如int为4字节,则要从4的整数倍地址开始存
储。 min(当前开始的位置m,n) m=9 n=4 9 10 11 12
2.结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从
其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b
里有char,int ,double等元素,那b应该从8的整数倍开始存储.)
3.收尾工作:结构体的总大小,也就是sizeof的结果,.必须是其内部最大
成员的整数倍.不足的要补⻬。

拿上面的两个结构体举例说明

struct Mystruct1{
    char a;     //1字节 从 0开始 1结束  min(0,1)
    double b;   //8字节 从 1开始 1不能整除8 从8开始 8到15 min(8,8)
    int c;      //4字节 从 16开始 能整除4 16到19
    short d;    //2字节 从 20开始 20能整除2 20到21
}Mystruct1;

最后 Mystruct1 中变量最大字节是8 Mystruct1 0-21 共22字节  22向上取整8的倍数 = 24, sizeof(Mystruct1)=24

struct Mystruct3{
    int a;              //4字节 min(0,4)--- (0,1,2,3)
    struct Mystruct4{  
     //从4开始,存储开始位置必须是最大的整数倍(最大成员为8),min(4,8)不满足, min(8,8)满          足,从8开始存储
        double b;       //8字节 min(8,8)  --- (8,9,10,11,12,13,14,15)
        short c;        //2字节,从16开始,min(6,2) -- (16,17,18)
        char d;          //1字节,从19开始,min(19,1) -- (19)
    }Mystruct4;
}Mystruct3;
 
Mystruct3 内存大小必须是 Mystruct4 中变量最大字节数即8的倍数 Mystruct3 0-19 共20个字节 20向上取整8的倍数=24

打印内存大小方法

sizeof 最终得到的结果是该数据类型占用空间的大小
class_getInstanceSize 获取类的实例对象所占用的内存大小
malloc_size 获取系统实际分配的内存大小

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSObject *objc = [[NSObject alloc] init];
        NSLog(@"objc对象类型占用的内存大小:%lu",sizeof(objc));
        NSLog(@"objc对象实际占用的内存大小:%lu",class_getInstanceSize([objc class]));
        NSLog(@"objc对象实际分配的内存大小:%lu",malloc_size((__bridge const void*)(objc)));
    }
    return 0;
}

打印 8 8 16

内存对齐算法

align16: 16字节对齐算法
static inline size_t align16(size_t x) {
    return (x + size_t(15)) & ~size_t(15);
}

#define SHIFT_NANO_QUANTUM      4
#define NANO_REGIME_QUANTA_SIZE (1 << SHIFT_NANO_QUANTUM)   // 16

static MALLOC_INLINE size_t
segregated_size_to_fit(nanozone_t *nanozone, size_t size, size_t *pKey)
{
    size_t k, slot_bytes;

    if (0 == size) {
        size = NANO_REGIME_QUANTA_SIZE; // Historical behavior
    }
    k = (size + NANO_REGIME_QUANTA_SIZE - 1) >> SHIFT_NANO_QUANTUM; // round up and shift for number of quanta
    slot_bytes = k << SHIFT_NANO_QUANTUM;                           // multiply by power of two quanta size
    *pKey = k - 1;                                                  // Zero-based!

    return slot_bytes;
}

算法原理:k + 15 >> 4 << 4 ,其中 右移4 + 左移4相当于将后4位抹零,跟 k/16 * 16一样 ,是16字节对齐算法,小于16就成0了

对于一个对象来说,其真正的对齐方式 是 8字节对齐,8字节对齐已经足够满足对象的需求了
apple系统为了防止一切的容错,采用的是16字节对齐的内存,主要是因为采用8字节对齐时,两个对象的内存会紧挨着,显得比较紧凑,而16字节比较宽松,利于苹果以后的扩展。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343