結構體(struct
)或者聯合體(union
)的數據成員,第一個數據成員放在offset爲0的地方,之後每一個數據成員存儲的起始位置要從該成員大小或者成員的子成員大小(只要該成員有子成員,好比說是數組,結構體等)的整數倍開始(好比int
爲4字節,則要從4的整數倍地址開始存儲)。express
若是一個結構裏有某些結構體成員,則結構體成員要從其內部最大元素大小的整數倍地址開始存儲。(struct a裏存有struct b,b裏有char,int,double等元素,那b應該從8的整數倍開始存儲)。數組
結構體的總大小,也就是sizeof的結果,必須是其內部最大成員的整數倍。不足的要補齊。markdown
C | OC | 32位 | 64位 |
---|---|---|---|
bool | BOOL(64位) | 1 | 1 |
signed char | (__signed char)int8_t、BOOL(32位) | 1 | 1 |
unsigned char | Boolean | 1 | 1 |
short | int16_t | 2 | 2 |
unsigned short | unichar | 2 | 2 |
int 、int32_t | NSInteger(32位)、boolean_t(32位) | 4 | 4 |
unsigned int | boolean_t(64位)、NSUInteger(32位) | 4 | 4 |
long | NSInteger(64位) | 4 | 8 |
unsigned long | NSUInteger(64位) | 4 | 8 |
long long | int64_t | 8 | 8 |
float | CGFloat(32位) | 4 | 4 |
double | CGFloat(64位) | 8 | 8 |
sizeof()
是C/C++
中的關鍵字,它是一個運算符,不是函數。做用是取得一個對象(數據類型或者數據對象)的長度(即佔用內存的大小,以byte
爲單位,返回size_t
)。基本數據類型(int
、double
等)的大小與系統相關。結構體涉及字節對齊。函數
示例:post
struct Stu {
char c;
int i;
double d;
};
void test() {
//基本數據類型
int age = 18;
size_t sizeAge1 = sizeof(age);
size_t sizeAge2 = sizeof age;
size_t sizeAge3 = sizeof(int);
NSLog(@"age size: %zu, %zu, %zu",sizeAge1,sizeAge2,sizeAge3);
//結構體
struct Stu s;
s.c = 'c';
s.i = 18;
s.d = 180.0;
size_t sizeS1 = sizeof(s);
size_t sizeS2 = sizeof s;
size_t sizeS3 = sizeof(struct Stu);
NSLog(@"s size: %zu, %zu, %zu",sizeS1,sizeS2,sizeS3);
//指針
NSObject *obj = [NSObject alloc];
size_t sizeObj1 = sizeof(obj);
size_t sizeObj2 = sizeof obj;
size_t sizeObj3 = sizeof(NSObject *);
NSLog(@"obj size: %zu, %zu, %zu",sizeObj1,sizeObj2,sizeObj3);
}
複製代碼
輸出:spa
age size: 4, 4, 4
s size: 16, 16, 16
obj size: 8, 8, 8
複製代碼
sizeof
是運算符不是函數。3種語法形式均可以,須要注意的是經過類型獲取的方式必須在()
中。這個函數是rutime
提供的獲取類的實例鎖佔用的內存大小。大小至於成員變量有關。獲取的是實際佔用的空間(8字節對齊
)。指針
malloc_size
就是alloc
中實際開闢的空間。code
Struct1
和Struct2
分別佔用多大內存?struct Struct1 {
double a; // [0,7]
char b; // [8]
int c; // 根據第一準則要從4的倍數開始,因此[12,13,14,15]。跳過9,10,11
short d; //[16,17]
}struct1;
//根據第三準則總大小要是8的倍數,那就要分配24字節。
struct Struct2 {
double a; //[0,7]
int b; //[8,11]
char c; //[12]
short d; //根據準則1跳過13,從14開始 [14,15]
}struct2;
//這裏0~15大小原本就爲16了,因此不須要補齊了。
複製代碼
驗證:orm
NSLog(@"struct1 size :%zu\nstruct2 size:%zu",sizeof(struct1),sizeof(struct2));
複製代碼
輸出:對象
struct1 size :24
struct2 size:16
複製代碼
0
開始,Struct2
並無進行第三原則補齊。Struct3
中有結構體嵌套,那麼佔用大小是多少?struct Struct3 {
double a; //[0,7]
int b; //[8,11]
char c; //[12]
short d; //跳過13 [14,15]
int e; // [16,19]
struct Struct1 str; //根據準則2,Struct1最大元素爲`double`類型,因此從24開始。根據`Struct1`分配的時候24個字節,因此str爲[24,47]
}struct3;
//因此Struct3佔用內存大小爲48字節。
複製代碼
驗證:
NSLog(@"struct3 size :%zu",sizeof(struct3));
struct3 size :48
複製代碼
在這裏有個疑問,準則3
是先做用在Struct1
再做用Struct3
仍是最後直接做用在Struct3
?不妨驗證一下:
struct Struct4 {
struct Struct1 str;
char c;
}struct4;
複製代碼
Struct1
自己佔用18字節
,補齊後佔用24字節
。若是Struct4
最終佔用32字節那麼就是第一種狀況,張永24 字節則是第二種狀況。
NSLog(@"struct4 size :%zu",sizeof(struct4));
struct4 size :32
複製代碼
這也就驗證了猜測,結構體嵌套從內部開始補齊。這也符合常理。
struct S1 {
int a; // 4 [0,3]
char b;// 1 [4]
short c; // 2 [6,7]
}; // 0~7 8字節
struct S2 {
double a; // 8 [0,7]
char b; // 1 [8]
struct S1 s1; // 8 [12,19] 按s1自身中存的最大a的4字節的倍數對齊
bool c; // 1 [20]
};
//0~20一共21個字節,按最大的8字節對齊。應該24字節。
複製代碼
struct S2 s2;
NSLog(@"size :%zu",sizeof(s2));
複製代碼
這個時候s2
大小爲多少?
分析:
S1:
int a
佔4
個字節,從[0~3]
。char b
佔1
個字節,[4]
。short c
佔2
個字節,須要以2
字節對齊,因此跳過5
[6~7]
S1
總體從0~7
不須要補齊。佔8
字節。S2:
double a
佔8
字節,[0~7]
。char b
佔1
字節,[8]
。struct S1 s1
佔8
字節。因爲S1
內部最大元素爲int a
因此須要4
倍對齊,因此[12~19]
。bool c
佔1
字節,[20]
。S2
總體從0~21
一共21
字節,須要按S2
中最大元素double a
補齊。因此應該是24
字節。輸出:
size :24
複製代碼