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