結構體內存對齊

影響對象內存的因素

思考:影響對象內存的因素有哪些?屬性、成員變量、方法 ?數組

@interface ABPerson : NSObject
@end
複製代碼

圖片.png ABPerson沒有添加任何屬性、成員變量、方法,輸出是8,這是isa佔用的8個字節markdown

添加方法後:app

圖片.png 依然是8,因此方法不佔用對象內存佈局

添加屬性:ui

@interface ABPerson : NSObject
@property (nonatomic,strong) NSString *nickName;
@end

複製代碼

圖片.png 去掉isa佔用的8個字節,當前屬性也佔用8個字節atom

添加成員變量:spa

@interface ABPerson : NSObject
{
    NSString *_nickName;
}
@end
複製代碼

圖片.png 成員變量也是佔用內存的。3d

因此,影響對象內存的是屬性、成員變量,方法不佔用對象內存。code

對象的內存佈局

lldb查看ABPerson對象的內存佈局orm

@interface ABPerson : NSObject
-(void)doSomething;
@end
複製代碼
@interface ABPerson : NSObject
{
    char _c3;
}
@property (nonatomic,strong) NSString *nickName;
@property (nonatomic,assign) int age;
@property (nonatomic) char c1;
@property (nonatomic) char c2;

@end
複製代碼
#import "ABPerson.h"

@implementation ABPerson
- (instancetype)init
{
    self = [super init];
    if (self) {
        _c3 = 'c';
    }
    return self;
}

@end

複製代碼
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#import "ABPerson.h"
#import <objc/runtime.h>
int main(int argc, char * argv[]) {
    NSString * appDelegateClassName;
    @autoreleasepool {
        
        ABPerson *p = [[ABPerson alloc] init];
        p.nickName = @"王";
        p.age = 18;
        p.c1 = 'a';
        p.c2 = 'b';
        NSLog(@"%zu",class_getInstanceSize(ABPerson.class));//24
        
        
        appDelegateClassName = NSStringFromClass([AppDelegate class]);
    }
    return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}

複製代碼

圖片.png

a、b、c的ASCII碼分別是9七、9八、99,因此年齡、c一、c二、c3共用了這8個字節,這就是結構體內存對齊

結構體內存對齊

內存對齊原則

  • 數據成員對⻬規則:結構(struct)(或聯合(union))的數據成員,第一個數據成員放在offset爲0的地方,之後每一個數據成員存儲的起始位置要從該成員大小或者成員的子成員大小(只要該成員有子成員,好比說是數組,結構體等)的整數倍開始(好比int爲4字節,則要從4的整數倍地址開始存儲。
  • 結構體做爲成員:若是一個結構裏有某些結構體成員,則結構體成員要從其內部最大元素大小的整數倍地址開始存儲.(struct a裏存有structb,b裏有char,int ,double等元素,那b應該從8的整數倍開始存儲.)
  • 收尾工做:結構體的總大小,也就是sizeof的結果,必須是其內部最大成員的整數倍.不足的要補⻬。
struct ABStruct1 {
    double a;  //8 [0...7]
    char b;    //1 [8]
    int c;     //4 9,10,11,[12,13,14,15]
    short d;   //2 [16,17]
}struct1;      //24
struct ABStruct2 {
    double a;  //8 [0...7]
    int b;     //4 [8,9,10,11]
    char c;    //1 [12]
    short d;   //2 13,[14,15]
}struct2;      //16

struct ABStruct3 {
    double a;  //8 [0...7]
    int b;     //4 [8,9,10,11]
    char c;    //1 [12]
    short d;   //2 13,[14,15]
    int e;     //4 [16,17,18,19]
    struct ABStruct1 str; //24 20,21,22,23,[24...47],
}struct3;      //48
複製代碼

註釋代碼部分,分別是不一樣類型變量所佔字節大小,和佔用內存空間的索引。 按照內存對齊原則,分析ABStruct1的結構體內存對齊:

  • a是double類型佔用8個字節,佔用索引0到7,
  • b是char類型佔用1個字節,索引位置必須是當前類型(char類型)的整數倍,接下來的索引8是1的倍數,b佔用索引8,
  • c是int類型佔用4個字節,接下來的索引9,10,11都不是4的倍數,索引12是,因此c佔用索引12到15
  • d是short類型佔用2個字節,索引16是2的倍數,因此d佔用索引1六、17
  • 又由於結構體的總大小必須是其內部最大成員的整數倍.不足的要補⻬,知足索引最大成員8的倍數又要裝下全部變量的最小值就是24

同理ABStruct1是16,ABStruct3是48 代碼驗證:

圖片.png

相關文章
相關標籤/搜索