OC底層-對象內(nèi)存的影響因素與結(jié)構(gòu)體內(nèi)存對齊原則

一 、對象內(nèi)存的影響因素理解
1.)場景1首先我們創(chuàng)建一個LGPerson繼承NSObject對象,里面沒有任何屬性,成員變量 和方法;

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface LGPerson : NSObject

@end

NS_ASSUME_NONNULL_END
#import "LGPerson.h"
@implementation LGPerson

@end
int main(int argc, char * argv[]) {
    NSString * appDelegateClassName;
    @autoreleasepool {

        LGPerson *person = [LGPerson alloc];
        
        lg_double2HEX(190.5);
        lg_float2HEX(190.5);
        appDelegateClassName = NSStringFromClass([AppDelegate class]);
    }
    return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
(lldb) po class_getInstanceSize(LGPerson.class)
8
(lldb) po class_getInstanceSize(NSObject.class)
8
(lldb)

場景1打印結(jié)果顯示:沒有添加任何成員屬性 LGPerson 與 NSObject的內(nèi)存長度都為8,兩者一樣;

2.)場景2,接著往LGPerson里面添加一個屬性name,

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface LGPerson : NSObject
//{
// NSString *name;
//}

@property (nonatomic, copy) NSString *name;
//+ (void)sayNB;
//- (void)sayNB2;
@end

NS_ASSUME_NONNULL_END
#import "LGPerson.h"
@implementation LGPerson
//+ (void)sayNB{
//}
//- (void)sayNB2;
//}
@end
int main(int argc, char * argv[]) {
    NSString * appDelegateClassName;
    @autoreleasepool {

        LGPerson *person = [LGPerson alloc];
   
        
        lg_double2HEX(190.5);
        lg_float2HEX(190.5);
        appDelegateClassName = NSStringFromClass([AppDelegate class]);
    }
    return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}

(lldb) po class_getInstanceSize(LGPerson.class)
16

(lldb) po class_getInstanceSize(NSObject.class)
8

(lldb) 

運(yùn)行結(jié)果發(fā)現(xiàn),此時LGPerson添加一個屬性name后,內(nèi)存長度為16,而NSObject 還是8;且在場景2基礎(chǔ)添加實例方法和類方法打印的結(jié)果一樣;在LGPerson將 name新建換成成員變量,打印結(jié)果也一樣;

3.)場景3:在場景2的基礎(chǔ)上,LGPerson多增加一個屬性

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface LGPerson : NSObject

@property (nonatomic, copy) NSString *name;

@property (nonatomic, copy) NSString *nickName;

@end

NS_ASSUME_NONNULL_END
(lldb) po class_getInstanceSize(LGPerson.class)
24

(lldb) po class_getInstanceSize(NSObject.class)
8

(lldb) 

打印輸出結(jié)果LGPerson,內(nèi)存長度變?yōu)樵瓉?4,而NSObject 內(nèi)存長度還是8;綜合場景1,2,3,繼承NSObject的對象,可否認(rèn)為每增加一個屬性,內(nèi)存長度就加8?繼續(xù)往下做驗證:

A:

@interface LGPerson : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *nickName;
@property (nonatomic, copy) NSString *hobby;
@end
(lldb) po class_getInstanceSize(LGPerson.class)
32
(lldb) 
@interface LGPerson : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *nickName;
@property (nonatomic, copy) NSString *hobby;
@property (nonatomic, assign) int age;
@end
(lldb) po class_getInstanceSize(LGPerson.class)
40
(lldb) 
@interface LGPerson : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *nickName;
@property (nonatomic, copy) NSString *hobby;
@property (nonatomic, assign) int age;
@property (nonatomic) double height;
@end
(lldb) po class_getInstanceSize(LGPerson.class)
48
(lldb) 
@interface LGPerson : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *nickName;
@property (nonatomic, copy) NSString *hobby;
@property (nonatomic, assign) int age;
@property (nonatomic) double height;
@property (nonatomic) char c1;
@property (nonatomic) char c2;
@end
(lldb) po class_getInstanceSize(LGPerson.class)
48
(lldb) 

此時發(fā)現(xiàn),LGPerson ,每增加一個屬性,內(nèi)存長度并不就加8,而是以8字節(jié)長度方式進(jìn)行對齊的:接下來:

int main(int argc, char * argv[]) {
    NSString * appDelegateClassName;
    @autoreleasepool {

                LGPerson *person = [LGPerson alloc];
                person.name      = @"Cooci";
                person.nickName  = @"KC";
                person.age       = 18;
                person.height    = 190.5;
                person.c1        = 'a';
                person.c2        = 'b';
        
        lg_double2HEX(18);
        lg_float2HEX(190.5);
        appDelegateClassName = NSStringFromClass([AppDelegate class]);
    }
    return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}

進(jìn)行打?。?/p>

(lldb) x/8gx person
0x60000366ed90: 0x00000001010b3860 0x0000001200006261
0x60000366eda0: 0x00000001010ae038 0x00000001010ae058
0x60000366edb0: 0x0000000000000000 0x4067d00000000000
0x60000366edc0: 0x0000000000000000 0x0000000000000000
(lldb) po 0x00000001010ae038
Cooci

(lldb) po 0x00000001010ae058
KC

(lldb) po 0x00000012
18

(lldb) po 0x61
97

(lldb) po 0x62
98

(lldb) e -f f -- 0x4067d00000000000
(long) $7 = 190.5
(lldb) 

總結(jié):LGPerson內(nèi)存的大小受成員變量,屬性的影響,不受方法的影響,而且以某種長度方式進(jìn)行對齊的。

二、結(jié)構(gòu)體內(nèi)存對齊原則
1.對齊原則
1):數(shù)據(jù)成員對?規(guī)則:結(jié)構(gòu)(struct)(或聯(lián)合(union))的數(shù)據(jù)成員,第?個數(shù)據(jù)成員放在offset為0的地?,以后每個數(shù)據(jù)成員存儲的起始位置要從該成員??或者成員的?成員??(只要該成員有?成員,?如說是數(shù)組,結(jié)構(gòu)體等)的整數(shù)倍開始(?如int為4字節(jié),則要從4的整數(shù)倍地址開始存儲。 min(當(dāng)前開始的位置m n) m = 9 n = 4
9 10 11 12
2):結(jié)構(gòu)體作為成員:如果?個結(jié)構(gòu)?有某些結(jié)構(gòu)體成員,則結(jié)構(gòu)體成員要從其內(nèi)部最?元素??的整數(shù)倍地址開始存儲.(struct a?存有struct b,b?有char,int ,double等元素,那b應(yīng)該從8的整數(shù)倍開始存儲.)
3):收尾?作:結(jié)構(gòu)體的總??,也就是sizeof的結(jié)果,.必須是其內(nèi)部最?成員的整數(shù)倍.不?的要補(bǔ)?。

各個成員所占字節(jié)數(shù)對應(yīng)表:


成員所占字節(jié)數(shù).png

2.例子1

struct LGStruct1 {
    double a;       // 8    [0 7]
    char b;         // 1    [8]
    int c;          // 4    (9 10 11 [12 13 14 15]
    short d;        // 2    [16 17] 24
}struct1;

struct LGStruct2 {
    double a;       // 8    [0 7]
    int b;          // 4    [8 9 10 11]
    char c;         // 1    [12]
    short d;        // 2    (13 [14 15] 16
}struct2;


struct LGStruct3 {
    double a;   // 8    [0 7]
    int b;      // 4    [8 9 10 11]
    char c;     // 1    [12]
    short d;    // 2    (13 [14 15] 16
    int e;      // 4    [16 17 18 19] 20 21 22 23 24
    struct LGStruct1 str; // 24 (20 21 22 23 [24 25 26 27 ....45 46 47] 48
}struct3;

struct LGStruct4 {
    double a;   // 8    [0 7]
    int b;      // 4    [8 9 10 11]
//    char c;     // 1
//    short d;    // 2
//    int e;      // 4
    struct LGStruct1 str; // (12 13 14 15  [16  25 26 27 ....33,34] 35 36 37 38 39 40)
}struct4;

int main(int argc, char * argv[]) {
    NSString * appDelegateClassName;
    @autoreleasepool {
         NSLog(@"%lu-%lu-%lu-%lu",sizeof(struct1),sizeof(struct2),sizeof(struct3),sizeof(struct4));

        appDelegateClassName = NSStringFromClass([AppDelegate class]);
    }
    return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
(lldb) 

打印結(jié)果

2021-06-09 09:13:39.137431+0800 001-內(nèi)存對齊原則[82125:2053942] 24-16-48-40
(lldb) 

感謝cooci老師的課程指導(dǎo),以上是學(xué)習(xí)過程中一些記錄,不足之處還請大家指出,好做改進(jìn)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容