C语言重难点:内存对齐和位段
一:結(jié)構(gòu)體內(nèi)存對(duì)齊
(1)為什么要存在內(nèi)存對(duì)齊
平臺(tái)原因(移植原因): 不是所有的硬件平臺(tái)都能訪問(wèn)任意地址上的任意數(shù)據(jù)的;某些平臺(tái)只能在某些地址處取得某些特定類型的數(shù)據(jù),否則拋出硬件異常。比如,當(dāng)一個(gè)平臺(tái)要取一個(gè)整型數(shù)據(jù)時(shí)只能在地址為4的倍數(shù)的位置取得,那么這時(shí)就需要內(nèi)存對(duì)齊,否則無(wú)法訪問(wèn)到該整型數(shù)據(jù)。
性能原因: 數(shù)據(jù)結(jié)構(gòu)(尤其是棧):應(yīng)該盡可能的在自然邊界上對(duì)齊。原因在于,為了訪問(wèn)未對(duì)齊內(nèi)存,處理器需要作兩次內(nèi)存訪問(wèn);而對(duì)齊的內(nèi)存訪問(wèn)僅需一次。
核心思想就是:以空間換取時(shí)間
(2)結(jié)構(gòu)體對(duì)齊規(guī)則
- 第一個(gè)成員在與結(jié)構(gòu)體變量偏移量為0的地址處。(即結(jié)構(gòu)體的首地址處,即對(duì)齊到0處)
- 其他成員變量要對(duì)齊到某個(gè)數(shù)字(對(duì)齊數(shù))的整數(shù)倍的地址處。
- 結(jié)構(gòu)體的總大小為最大對(duì)齊數(shù)(每個(gè)成員變量都有一個(gè)對(duì)齊數(shù))的整數(shù)倍。
- 如果嵌套了結(jié)構(gòu)體,嵌套的結(jié)構(gòu)體對(duì)齊到自己的最大對(duì)齊數(shù)的整數(shù)倍處,結(jié)構(gòu)體的整體大小就是所有最大對(duì)齊數(shù)(含嵌套結(jié)構(gòu)體的對(duì)齊數(shù))的整數(shù)倍。
其中對(duì)齊數(shù)=編譯器默認(rèn)的一個(gè)對(duì)齊數(shù)與該成員大小的較小值。vs中默認(rèn)為8。Linux中默認(rèn)值為4。
(3)結(jié)構(gòu)體對(duì)齊演示
以下面的構(gòu)體為例
struct S {double d;char c;int i; };第一步:把結(jié)構(gòu)體中每個(gè)成員變量的大小與編譯器的默認(rèn)對(duì)齊數(shù)進(jìn)行比較,取小的作為該成員的對(duì)齊數(shù)
第二步:從0位開(kāi)始,畫(huà)出這些成員的位置,注意對(duì)齊到自己的對(duì)齊數(shù)
故為16個(gè)字節(jié)
(4)練習(xí)
//練習(xí)1 struct S1{char c1;int i;char c2; }; printf("%d\n", printf(struct S1);//12//練習(xí)2 struct S2 {char c1; char c2; int i; }; printf("%d\n", sizeof(struct S2));//8//練習(xí)3 struct S3 {double d; char c; int i; }; printf("%d\n", sizeof(struct S3));//16//練習(xí)4-結(jié)構(gòu)體嵌套問(wèn)題 struct S4 {char c1; struct S3 s3; double d; }; printf("%d\n", sizeof(struct S4));//32下面這個(gè)例子比較經(jīng)典(64位)
struct A {int a;union{long b;short c;}; }; struct B {char e;struct A d;int f; };二:位段
(1)什么是位段
“節(jié)省空間”這四個(gè)字可以直截了當(dāng)?shù)狞c(diǎn)名位段的作用。
在結(jié)構(gòu)體設(shè)計(jì)中,我們一般用int來(lái)存年齡這樣的數(shù)據(jù),但是年齡這個(gè)東西再大也不會(huì)達(dá)到幾百幾千,也就是它的范圍一般是1-100,反應(yīng)、、反映在整形數(shù)據(jù)的內(nèi)存上,使用的可能就是32個(gè)比特位中的個(gè)別幾個(gè),也就說(shuō)剩余的很多比特位就是根本不會(huì)用到的,而如果明知道這樣,還要不管三七二十一直接拋出一個(gè)整形,四個(gè)字節(jié),32個(gè)比特位存儲(chǔ)這么小的數(shù),未免顯的有點(diǎn)浪費(fèi)了。所以正式鑒于此,位段就能合理的進(jìn)行內(nèi)存設(shè)計(jì)
(2)位段怎么寫
位段的基本格式如下,和結(jié)構(gòu)體十分相似,其內(nèi)部的數(shù)據(jù)類型一般要求是一致的
(3)位段結(jié)構(gòu)體對(duì)齊怎么算
上述這個(gè)結(jié)構(gòu)體所占空間大小為八個(gè)字節(jié),在實(shí)際分配時(shí),會(huì)一上來(lái)先分配四個(gè)字節(jié),其中a,b,c占據(jù)2+5+10共17個(gè)比特位,剩余d需要30個(gè)比特位存儲(chǔ)但是不夠,所以再分配四個(gè)字節(jié),拿出其中30個(gè)比特位存儲(chǔ)。可以看出相比之前暴力的直接16個(gè)字節(jié),現(xiàn)在的8個(gè)字節(jié)大大的節(jié)省了空間。
再比如下面位段
struct A {unsigned a : 19;unsigned b : 11;unsigned c : 4;unsigned d : 29; char index; };其中a和b共占據(jù)4個(gè)字節(jié),c和d占據(jù)八個(gè)字節(jié),index對(duì)齊對(duì)齊1個(gè)字節(jié),最終就是16
總結(jié)
以上是生活随笔為你收集整理的C语言重难点:内存对齐和位段的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: opencv3.10加入OPENCV_c
- 下一篇: (计算机组成原理)第五章中央处理器-第一