解析C語言中結(jié)構(gòu)體struct的對(duì)齊問題
首先看一下結(jié)構(gòu)體對(duì)齊的三個(gè)概念值:
數(shù)據(jù)類型的默認(rèn)對(duì)齊值(自身對(duì)齊):
1.基本數(shù)據(jù)類型:為指定平臺(tái)上基本類型的長(zhǎng)度。如在32位機(jī)器中,char對(duì)齊值為1,short為2,int,float為4,double為8;
結(jié)構(gòu)體:其數(shù)據(jù)成員中默認(rèn)對(duì)齊值最大的那個(gè)值。
2.指定對(duì)齊值:#pragma pack (value)時(shí)的指定對(duì)齊值value。
3.數(shù)據(jù)類型的有效對(duì)齊值:默認(rèn)對(duì)齊值和指定對(duì)齊值中小的那個(gè)值。
有了這些值,我們就可以很方便的來討論具體數(shù)據(jù)結(jié)構(gòu)的成員和其自身的對(duì)齊方式。有效對(duì)齊值N是最終用來決定數(shù)據(jù)存放地址方式的值,最重要。有效對(duì)齊N,就是表示“對(duì)齊在N上”,也就是說該數(shù)據(jù)的“偏移量%N=0”。而數(shù)據(jù)結(jié)構(gòu)中的數(shù)據(jù)變量都是按定義的先后順序來排放的。第一個(gè)數(shù)據(jù)變量的起始地址就是數(shù)據(jù)結(jié)構(gòu)的起始地址。結(jié)構(gòu)體的成員變量要對(duì)齊排放(對(duì)于非對(duì)齊成員需要在其前面填充一些字節(jié),保證其在對(duì)齊位置上),結(jié)構(gòu)體本身也要根據(jù)自身的有效對(duì)齊值圓整(就是結(jié)構(gòu)體總長(zhǎng)度需要是結(jié)構(gòu)體有效對(duì)齊值的整數(shù)倍)。
通過上面的分析,對(duì)結(jié)構(gòu)體進(jìn)行字節(jié)對(duì)齊,我們需要知道四個(gè)值:
- 指定對(duì)齊值:代碼中指定的對(duì)齊值,記為packLen;
- 默認(rèn)對(duì)齊值:結(jié)構(gòu)體中每個(gè)數(shù)據(jù)成員及結(jié)構(gòu)體本身都有默認(rèn)對(duì)齊值,記為defaultLen;
- 成員偏移量:即相對(duì)于結(jié)構(gòu)體起始位置的長(zhǎng)度,記為offset;
- 成員長(zhǎng)度:結(jié)構(gòu)體中每個(gè)數(shù)據(jù)成員的長(zhǎng)度(注結(jié)構(gòu)體成員為補(bǔ)齊之后的長(zhǎng)度),記為memberLen。
及兩個(gè)規(guī)則:
1.對(duì)齊規(guī)則:
offset % vaildLen = 0,其中vaildLen為有效對(duì)齊值vaildLen = min(packLen, defaultLen);
2.填充規(guī)則:
如成員變量不遵守對(duì)齊規(guī)則,則需要對(duì)其補(bǔ)齊;在其前面填充一些字節(jié)保證該成員對(duì)齊。需填充的字節(jié)數(shù)記為padLen:
padLen = getPadLen(offset , defaultLen); int getPadLen(int offsetLen, int defaultLen) { int vaildLen = min(packLen,defaultLen); if(0 == vaildLen || 0 == offsetLen % vaildLen) { return 0; } return vaildLen - (offsetLen % vaildLen); }
結(jié)構(gòu)體對(duì)齊算法思想:深度優(yōu)先填充
先對(duì)齊內(nèi)層結(jié)構(gòu)體;
對(duì)每個(gè)數(shù)據(jù)成員計(jì)算其defaultLen、memberLen和offset;
再遍歷每個(gè)數(shù)據(jù)成員時(shí)計(jì)算;
對(duì)于基本數(shù)據(jù)類型成員defaultLen=memberLen;對(duì)于結(jié)構(gòu)體成員defaultLen等于它的所有成員的最大的memberLen;
遍歷時(shí)對(duì)成員的memberLen進(jìn)行累加,得到當(dāng)前成員的offsetLen;
運(yùn)用對(duì)齊及填充規(guī)則:在當(dāng)前結(jié)構(gòu)體成員前填充padLen個(gè)字節(jié);
舉例說明:
struct{ short a; short b; short c; }A; sizeof(A) = 6;
(vc6與gcc相同)
struct{ long a; short c; }A; sizeof(A) = 8;
(vc6與gcc相同), 它的內(nèi)存分配為: a1 a2 a3 a4 , c1 c2 x x(a1為a的第一個(gè)字節(jié),x為補(bǔ)齊字節(jié),下同)
struct{ int a; char b; short c; }A; sizeof(A) = 8;
A的內(nèi)存分配為:
a1 a2 a3 a4, b1 x c1 c2
struct{ char a; int b; short c; }A1; sizeof(A1) = 12;
(vc6與gcc相同)
A1的內(nèi)存分配為:
a1 x x x, b1 b2 b3 b4, c1 c2 x x
下面是更復(fù)雜的情況,結(jié)構(gòu)體作為成員
struct{ int a; doubl b; short c; }A; // sizeof(A) = 24 (vc6與gcc相同) struct{ char a,b; int c; double d; short e; struct A h; }B; sizeof(B) = 48 //(vc6與gcc相同)
A的內(nèi)存分布:
a1 a2 a3 a4 x x x x, b1 b2 b3 b4 b5 b6 b7 b7, c1 c2 x x x x x x
B的內(nèi)存分布:
a1 b1 x x, c1 c2 c3 c4 , d1 d2 d3 d4 d5 d6 d7 d8, e1 e2 x x x x
上一篇:實(shí)例解析C++中類的成員函數(shù)指針
欄 目:C語言
下一篇:簡(jiǎn)明的C++函數(shù)指針學(xué)習(xí)教程
本文標(biāo)題:解析C語言中結(jié)構(gòu)體struct的對(duì)齊問題
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/2363.html
您可能感興趣的文章
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用函數(shù)刪除字符
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)式函數(shù)庫
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言中對(duì)數(shù)函數(shù)的表達(dá)式 c語言中對(duì)數(shù)怎么表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段函數(shù)
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排序法函數(shù)
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段函數(shù)
- 04-02C語言中怎么打出三角函數(shù) c語言中怎么打出三角函數(shù)的值
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求階乘


閱讀排行
- 1C語言 while語句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹的示例代碼(圣誕
- 3利用C語言實(shí)現(xiàn)“百馬百擔(dān)”問題方法
- 4C語言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對(duì)數(shù)函數(shù)的表達(dá)式 c語言中對(duì)
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機(jī)閱讀
- 04-02jquery與jsp,用jquery
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-11ajax實(shí)現(xiàn)頁面的局部加載
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-10delphi制作wav文件的方法
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-10使用C語言求解撲克牌的順子及n個(gè)骰子
- 01-10C#中split用法實(shí)例總結(jié)