位元組對齊不同造成結構體成員賦值失敗

2021-07-24 20:32:44 字數 1457 閱讀 6583

我們知道,c編譯器在編譯32位機目標**時,預設將變數儲存的位址按照4位元組進行對齊。

在使用結構體時,由於位元組對齊的原因可能會造成儲存空間的浪費

例如:struct aaaa

結果,sizeof(aa)=12

。成員a與b之間空出了3個空位元組,成員c也後也空出了3個位元組。

這個時候雖然記憶體空間有些浪費

,但是並不會誤導程式設計師進行編碼

。如果和聯合體一起使用

,就可能會造成一定的誤解。

例如:struct aa;

int data;

}}aa

此處本來想將 byte0 -byte3作為 data的4個位元組的重名以便對data的其中任意8bit進行操作。但是由於四位元組對齊的原因只有byte0是data的第0位元組,byte1-byte3每乙個成員都向後偏移了四個位元組。

為了達到預期的效果,可以使用#pragma pack(n) 對編譯器進行位元組對齊設定。

#pragma pack(1)//按照1位元組進行對齊

struct aa;

int data; }

}aa#pragma pack()//取消對齊設定

這樣就可以達到預想的效果,使用byte0-byte3對data的每個位元組進行單獨的操作。

但是今天,由於我在使用#pragma pack() 指令犯了錯誤,產生了結構體成員賦值失敗的情況。

情況如下:

檔案a

struct aaaa

檔案b#pragma pack(1)//按照1位元組進行對齊

struct _cc;

int data; }

}ccaa.b = 0x02;//此處給成員b賦值失敗

#pragma pack()//取消對齊設定

我在檔案a中使用預設的對齊設定(4位元組對齊),建立了結構體aa。然後aa作為全域性變數在檔案b中進行賦值。

但檔案b由於cc結構體的需要設定了1位元組對齊

對結構體aa成員的賦值語句放在了取消對齊設定之前,編譯器在編譯檔案b時對變數aa.b按照1位元組對齊進行了操作,所以成員b的偏移位址為1。而實際上在定義aa時,成員b的偏移位址為4(a與b之間插入了3個空位元組)

所以賦值並沒有成功,而是將0x02寫入了aa.a 與aa.b中間的填充位元組。

在**這段程式時,就出現了賦值不成功的奇怪現象。

那麼應該如何解決這個問題呢?

那就是謹慎的使用#pragma pack(n)指令

將需要對齊的結構體宣告放在#pragma pack(n) 與 #pragma pack()之間,其他的**不要放在這裡面,特別是對對齊設定不同的結構體進行訪問的**段。

檔案b改為

#pragma pack(1)//按照1位元組進行對齊

struct _cc;

int data; }

}cc#pragma pack()//取消對齊設定

aa.b = 0x02;//此處給成員b賦值成功

結構體位元組對齊

include pragma pack 2 struct t.pragma pack int main int argc,char argv 最後輸出的結果為 8。這個表示是按照2位元組來對齊資料,首先分配2位元組給成員變數i,分配完成後,還剩一位元組,zj add補0 沒法容納成員變數d,此時會再...

結構體位元組對齊

include pragma pack 2 struct t.pragma pack int main int argc,char argv 最後輸出的結果為 8。這個表示是按照2位元組來對齊資料,首先分配2位元組給成員變數i,分配完成後,還剩一位元組,zj add補0 沒法容納成員變數d,此時會再...

結構體位元組對齊

在用sizeof運算子求算某結構體所佔空間時,並不是簡單地將結構體中所有元素各自佔的空間相加,這裡涉及到記憶體位元組對齊的問題。從理論上講,對於任何 變數的訪問都可以從任何位址開始訪問,但是事實上不是如此,實際上訪問特定型別的變數只能在特定的位址訪問,這就需要各個變數在空間上按一定的規則排列,而不是...