02 - 内存对齐解析-结构体嵌套结构体

一 思考

struct Person{
   int a;
   char b;
   double c;
} person;

struct People{
    char b;
    double c;
    int a;
}people;
int main ()
{
    printf ("%d\n",sizeof(people);  
   printf ("%d\n",sizeof(person);  
    return 0;
}
各类型所占内存大小

真机运行,64位系统上 char + int + double = 1 + 4 + 8 应该占12个字节 ,但运行打印后发现为24 ,16,说明系统存储相应类型有其固定方式即为内存对齐

一 为什么要内存对齐

为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐,为了访问未对齐的内存,处理器需要作两次内存访问;然而,对齐的内存访问仅需要一次访问. 例如2-5 4字节数据,在没有内存对齐的情况下要取两次 0-3 4-7 才能得到2-5所需数据.

二 规则 - 如何计算

  • 假设m为当前成员起始存储位置 n为其所需存储大小 需满足 m % n == 0
    否则需从m+1位开始 直到满足条件
  • 当结构体嵌套了结构体时,以数据成员的结构体的自身长度作为外部结构体的最大成员的内存大小,比如结构体a嵌套结构体b,b中有charintdouble等,则b的自身长度为8开始计算b结构体内子成员位置
  • 最后结构体的内存大小必须是结构体中最大成员内存大小的整数倍,不足的需要补齐

解释下上面的24 16 是如何得到的:

Person 结构结构体
计算思路
  • int a 占4个字节从头开始
  • chat b 一个字节 占据 4号位
  • double 8个字节 5, 6 , 7, 无法整除8 故偏移到8号位置 开始到15号 共占8位
  • 结构体总大小位置为16 最大成员为double c8位 可被16整除 故返回16个字节
People 结构结构体
计算思路
  • chat b 从0开始 占一个字节
  • double c8个字节偏移到8号位置向后8位到15
    -int a 4字节可以被16整除 从16开始向后4位到19
  • 最大成员为double c8位, 向后补齐到23 ,共24位可整除8,返回24个字节
三 结构体嵌套结构体
struct Teacher{
    char d;
    int e;
    short f;
    int g;
}teacher;

struct tClass{
    char a;
    int b;
    short c; 
    struct Teacher teacher1;
}class;

int main ()
{
    printf ("%d\n",sizeof(class); //28
    return 0;
}
计算过程
  • chat a , int b , short c 如上面结构体一样计算到位置9
  • Class中最大成员为int 4字节 所以偏移到12号位置存储class中的chat d
  • 剩下的类似普通结构体直到27号位置存储完共28位 28 可以整除最大成员大小 int 4字节 返回28

三 拓展, 应用

  • pragma pack(n) & attribute((aligned (n)))

#pragma pack(1)
struct Person{
  int a;
  char b;
  double c;
} person;// sizeof(person) =  13
#pragma pack()

#define PACKED __attribute__((packed))
struct  PACKED People{
   char b;
   double c;
   int a;
}people;//sizeof(people) =  13
  • #pragma pack(n)为设置采用多少字节对齐
  • #define PACKED __attribute__((packed)) 取消编译过程中的优化对齐

四 OC中的内存优化

  • 由 Person 与People 我们可以得知,在启用内存对齐后,成员相同的结构体,成员顺序不同,则最后实际开辟内存大小也不同,并且所占内存大小大的成员在结构体位置靠前时,最终开辟的空间可能会更小. 不过OC中采用的是16字节对齐,这种方式优化没意义.

OC 属性重排验证

@interface Person : NSObject

@property(nonatomic,assign)NSInteger age;

@property(nonatomic,assign)BOOL sex;

@property(nonatomic,copy)NSString *name;

@property(nonatomic,copy)NSString *address;

@end

-声明一个对象Person 其属性顺序如上

  • 赋值
   Person *person = [[Person alloc] init];
   person.name = @"范热热";
   person.address = @"li bed";
   person.age = 100;
   person.height = 400;
   person.a = 'f';
   person.b = 'b';
  
   NSLog(@"objc对象类型占用的内存大小:%lu",sizeof(person));
   NSLog(@"objc对象实际占用的内存大小:%lu",class_getInstanceSize([Person class]));
   NSLog(@"objc对象分配的内存大小:%lu",malloc_size((__bridge const void*)(person)));
  

查看打印结果 为 8 40 48

  • sizeof(person) 得到的是person指针的大小 占8位 没毛病
  • malloc_size((__bridge const void*)(person)) 实际开辟的大小,采用16字节对齐要被16整除 得48 也可以
  • class_getInstanceSize([Person class]) 这个40是如何得到呢 答案是苹果实际采用的是8字节对齐 验证一下


    person 内存分布
  • 首先我们发现 实际内存中存储的属性值与我们在.h中定义的顺序并不一样
  • 第一个占8位的为ISA指针地址
  • 第二个8位 一共包含了 int age chat a chat b三个属性
  • 第三个8位 为 int height
  • 第四个第五个8位为 NSString 类型
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349