结构体内存对齐

影响对象内存的因素

思考:影响对象内存的因素有哪些?属性、成员变量、方法 ?数组

@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

相关文章
相关标签/搜索