C++中結(jié)構(gòu)體的字節(jié)對(duì)齊問(wèn)題 ---- 轉(zhuǎn)
前不久,在C++程序中碰到一個(gè)有關(guān)結(jié)構(gòu)體字節(jié)對(duì)齊的問(wèn)題。
一。問(wèn)題描述
在程序中,定義了一個(gè)結(jié)構(gòu)體,如下:
typedef struct
{
char name[33];
int ID;
int age;
} PERSON;
聲明了一個(gè)該結(jié)構(gòu)體的數(shù)組:
PERSON peo[30];
當(dāng)從結(jié)構(gòu)體中取出ID字段給一個(gè)int類型的局部變量賦值時(shí),卻出現(xiàn)異常.
比如結(jié)構(gòu)體中的字段都已經(jīng)有初始值
peo[0].ID =4;
下面的賦值語(yǔ)句
int tempID = peo[0].ID;
卻不能正確得到數(shù)值4,tempID得到的是67108864.
經(jīng)檢查67108864是4在高位時(shí)的數(shù)值大小.
賦值時(shí)本來(lái)應(yīng)該是取內(nèi)存中的四個(gè)Bytes:"04 00 00 00"
可是取值時(shí)卻是用"00 00 00 04" 的方式.
在調(diào)試過(guò)程中,從peo[0].ID取值是正確的,得到數(shù)字4,可程序執(zhí)行上面賦值語(yǔ)句后:
tempID還是得到的是67108864.
也就是說(shuō),在調(diào)試器中取值是正確的,匯編后的程序取值卻是不正確的.
程序在開始用了的很長(zhǎng)一段時(shí)間并沒有出現(xiàn)這種問(wèn)題,這個(gè)問(wèn)題是最近才發(fā)生的.
真是百思不得其解。還有一點(diǎn)是明確的,程序涉及到網(wǎng)絡(luò)傳輸。
可是如果把結(jié)構(gòu)體中的字符數(shù)組大小由33改為36,一切正常了!
原理上肯定是結(jié)構(gòu)體的位對(duì)齊問(wèn)題,但為什么以前編譯使用沒出問(wèn)題,現(xiàn)在編譯才發(fā)生呢?
應(yīng)該怎么解決呢?
二。尋找問(wèn)題的原因。
經(jīng)過(guò)CSDN社區(qū)各位老大的幫助,并且自己仔細(xì)去了解程序中的編譯條件部分,原則上理解了這問(wèn)題的本質(zhì)所在。
發(fā)現(xiàn)在網(wǎng)絡(luò)模塊中使用到了"#pram pack(1)"這樣的編譯條件,而其它模塊則沒有加入這種編譯條件。
而CSDN中其中一個(gè)大蝦是這樣解釋的:“對(duì)齊方式是給編譯器看的,編譯器根據(jù)這個(gè)來(lái)決定內(nèi)存布局。一旦編譯成二進(jìn)制文件內(nèi)存布局就已經(jīng)確定了,如果兩段代碼對(duì)同一個(gè)結(jié)構(gòu)使用的對(duì)齊方式不同,那么就會(huì)對(duì)內(nèi)存里的值做出了不同的解釋,賦值的一方認(rèn)為char[33]占了36個(gè)字節(jié),從第37個(gè)字節(jié)填寫04 00 00 00,可是讀取的一方認(rèn)為char[33]只有33個(gè)字節(jié),那就從第34個(gè)字節(jié)處取四個(gè)字節(jié)當(dāng)作ID。”
這次網(wǎng)友的解釋,我認(rèn)為指出了問(wèn)題的本質(zhì)所在:“如果兩段代碼對(duì)同一個(gè)結(jié)構(gòu)使用的對(duì)齊方式不同,那么就會(huì)對(duì)內(nèi)存里的值做出了不同的解釋”。我們的程序給結(jié)構(gòu)體初始化部分是按VC編譯器中默認(rèn)的結(jié)構(gòu)體8字節(jié)對(duì)齊,而在網(wǎng)絡(luò)模塊中,由于使用了"#pram pack(1)",結(jié)果從結(jié)構(gòu)體中取值時(shí),編譯器認(rèn)為結(jié)構(gòu)體是按1字節(jié)對(duì)齊,最終導(dǎo)致了問(wèn)題的產(chǎn)生。
三。解決方法
為了解決這個(gè)問(wèn)題,就需要程序中所有的代碼對(duì)同一個(gè)結(jié)構(gòu)體都使用同一種對(duì)齊即可。
會(huì)有兩種解決辦法:
一是把網(wǎng)絡(luò)模塊中的"#pram pack(1)"去掉,結(jié)構(gòu)體都是按VC編譯器中默認(rèn)的結(jié)構(gòu)體8字節(jié)方式對(duì)齊。
二是設(shè)置結(jié)構(gòu)體按1字節(jié)方式進(jìn)行對(duì)齊,程序所有模塊都按這種對(duì)齊方式編譯。
設(shè)置在VC的"project"->"setting..."->"c/c++":struct member aligment改成1 Bytes.
posted on 2008-11-05 23:30 大龍 閱讀(1963) 評(píng)論(0) 編輯 收藏 引用