聯(lián)合體
定義
聯(lián)合體也叫共用體,由不同的數(shù)據(jù)類型組成,其變量互斥,存儲(chǔ)方式是所有成員共用一個(gè)段內(nèi)存,共同體同一時(shí)刻只能保存一個(gè)成員的值,如果對(duì)新的成員賦值,就會(huì)將原來(lái)成員的值覆蓋掉。
特性
- 在
union中,分配內(nèi)容空間大小,等于占用內(nèi)存最大的數(shù)據(jù)類型字節(jié)大小 - 共享一段內(nèi)存,成員變量的賦值操作,其他成員變量原有數(shù)據(jù)將成為臟數(shù)據(jù),不可用。
例子
// 聯(lián)合體的定義
union Teacher {
char *name; // 8
int age; // 4
double height; // 8
};
- 驗(yàn)證聯(lián)合體大小
int main(int argc, const char * argv[]) {
@autoreleasepool {
// 聯(lián)合體
union Teacher teacher;
teacher.name = "AngaoTu";
teacher.age = 18;
teacher.height = 175.0;
NSLog(@"聯(lián)合體大小 size = %lu", sizeof(teacher));
}
return 0;
}
打印結(jié)果:2022-07-30 15:38:42.149406+0800 聯(lián)合體+位域[9304:21445471] 聯(lián)合體大小 size = 8
可證明聯(lián)合體的大小,是由占用內(nèi)存最大的數(shù)據(jù)類型字節(jié)大小決定
- 驗(yàn)證是否共用同一片地址
int main(int argc, const char * argv[]) {
@autoreleasepool {
// 聯(lián)合體
union Teacher teacher;
teacher.name = "AngaoTu";
teacher.age = 18;
teacher.height = 175.0;
NSLog(@"name 地址 = %p, age 地址 = %p, height 地址 = %p", &teacher.name, &teacher.age, &teacher.height);
}
return 0;
}
打印結(jié)果:2022-07-30 15:43:05.950276+0800 聯(lián)合體+位域[10267:21450499] name 地址 = 0x7ffeefbff398, age 地址 = 0x7ffeefbff398, height 地址 = 0x7ffeefbff398
可驗(yàn)證聯(lián)合體中成員變量使用同一個(gè)地址
- 驗(yàn)證一個(gè)成員被賦值,其他成員數(shù)據(jù)不可用
int main(int argc, const char * argv[]) {
@autoreleasepool {
// 聯(lián)合體
union Teacher teacher;
teacher.name = "AngaoTu";
teacher.age = 18;
teacher.height = 175.0;
}
return 0;
}
打印結(jié)果:
- (Teacher) teacher = (name = "AngaoTu", age = 16176, height = 2.1220037829711594E-314)
- (Teacher) teacher = (name = "", age = 18, height = 2.1219957998584539E-314)
- (Teacher) teacher = (name = "", age = 0, height = 175)
可驗(yàn)證成員變量的賦值操作,其他成員變量原有數(shù)據(jù)將成為臟數(shù)據(jù),不可用
優(yōu)缺點(diǎn)
- 優(yōu)點(diǎn):
- 內(nèi)存使用更為精細(xì)、節(jié)省空間
- 缺點(diǎn):
- 不夠包容,成員之間會(huì)互相影響
位域
定義
有些信息在存儲(chǔ)時(shí),并不需要占用一個(gè)完整的字節(jié),而只需占幾個(gè)或一個(gè)二進(jìn)制位。 例如在存放一個(gè)開關(guān)量時(shí),只有 0 和 1 兩種狀態(tài),用一位二進(jìn)位即可。為了節(jié)省存儲(chǔ)空間,并使處理簡(jiǎn)便,C語(yǔ)言又提供了一種數(shù)據(jù)結(jié)構(gòu),稱為“位域”或“位段”。
聲明
- 位域的定義和結(jié)構(gòu)體的定義相仿
sturct 位域結(jié)構(gòu)名 {
位域列表 // 格式: [類型 位域名:位域長(zhǎng)度]
};
struct bits {
int a: 8;
int b: 2;
int c: 6;
}
位域的大小
struct bits {
char a:2;
};
// size = 1
struct bits {
char a:2;
char b:2;
};
// size = 1
struct bits {
char a:2;
char b:2;
char c:4;
char d:4;
};
// size = 2
struct bits {
int a:4;
};
// size = 4
struct bits {
int a:4;
int b:4;
};
// size = 4
struct bits {
char a:8;
char b:8;
char c:8;
char d:8;
int e:4;
};
// size = 8
- 位域的存儲(chǔ)同樣遵循結(jié)構(gòu)體內(nèi)存對(duì)齊規(guī)則
- 選取該位域結(jié)構(gòu)內(nèi)聲明時(shí)的類型中長(zhǎng)度最大的類型長(zhǎng)度,為對(duì)齊方式
- 具體可參考結(jié)構(gòu)體內(nèi)存對(duì)齊【TODO】
特性說(shuō)明
- 當(dāng)相鄰成員,如果它們的位寬之和小于類型的
sizeof大小,那么后面的成員緊鄰前一個(gè)成員存儲(chǔ),直到不能容納為止;如果它們的位寬之和大于類型的 sizeof 大小,那么后面的成員將從新的存儲(chǔ)單元開始,其偏移量為類型大小的整數(shù)倍。 - 位域的寬度不能超過(guò)它所依附的數(shù)據(jù)類型的長(zhǎng)度,成員變量都是有類型的,這個(gè)類型限制了成員變量的最大長(zhǎng)度,: 后面的數(shù)字不能超過(guò)這個(gè)長(zhǎng)度。
- 位域可以是無(wú)名位域,這時(shí)它只用來(lái)作填充或調(diào)整位置。無(wú)名的位域是不能使用的
聯(lián)合體位域
定義
把聯(lián)合體和位域結(jié)合起來(lái)的數(shù)據(jù)類型,稱為聯(lián)合體位域
聲明
union isa_t {
uintptr_t bits;
#if defined(ISA_BITFIELD)
struct {
ISA_BITFIELD; // defined in isa.h
};
Class cls;
};
- 由于
isa_t是一個(gè)共用體,所以bits和cls共用一塊內(nèi)存空間。 -
bits是一個(gè)位域,里面根據(jù)不同位定義了數(shù)據(jù),節(jié)省空間。