最近遊戲專案開發中遇到一件麻煩事,客戶端unity開發用的c#,但需要呼叫c++中的函式進行訊息加密,呼叫dll中的介面時,c#中的結構體需要傳入到c++中進行操作,但是由於c#中的訊息頭定義的比較苟且,沒有提供乙個跟c++中一一對應的結構體,導致加密後再解密出錯,最後發現是記憶體位元組對齊的問題,在c++訊息頭定義處加入
#pragma pack(push, 1)
#pragma pack(pop)
即可,這裡順便總結下位元組對齊。
1. 基本概念
位元組對齊:計算機儲存系統中以byte為單位儲存資料,不同資料型別所佔的空間不同,如:整型(int)資料佔4個位元組,字元型(char)資料佔乙個位元組,短整型(short)資料佔兩個位元組,等等。計算機為了快速的讀寫資料,預設情況下將資料存放在某個位址的起始位置,如:整型資料(int)預設儲存在位址能被4整除的起始位置,字元型資料(char)可以存放在任何位址位置(被1整除),短整型(short)資料儲存在位址能被2整除的起始位置。這就是預設位元組對齊方式
2.資料成員對齊規則
結構(struct)(或聯合(union))的資料成員,第乙個資料成員放在offset為0的地方,以後每個資料成員儲存的起始位置要從該成員大小或者成員的子成員大小(只要該成員有子成員,比如說是陣列,結構體等)的整數倍開始(比如int在32位機為4位元組,則要從4的整數倍位址開始儲存
3. 舉例說明
很顯然預設對齊方式會浪費很多空間,例如如下結構:
struct student
本來只用了11bytes(5+4+2)的空間,但是由於int型預設4位元組對齊,存放在位址能被4整除的起始位置,即:如果name[5]從0開始存放,它佔5bytes,而num則從第8(偏移量)個位元組開始存放。所以sizeof(student)=16。於是中間空出幾個位元組閒置著。但這樣便於計算機快速讀寫資料,是一種以空間換取時間的方式。其資料對齊如下圖:
|char|char|char|char|
|char|----|----|----|
|--------int--------|
|--short--|----|----|
4. #pragma pack()命令
為了節省空間,我們可以在編碼時通過#pragma pack()命令指定程式的對齊方式,括號中是對齊的位元組數,若該命令括號中的內容為空,則為預設對齊方式。例如,對於上面第乙個結構體,如果通過該命令手動設定對齊位元組數如下:
#pragma pack(push,2) //設定2位元組對齊
struct strdent
#pragma pack() //取消設定的位元組對齊方式
則,num從第6(偏移量)個位元組開始存放,score從第10(偏移量)個位元組開始存放,故sizeof(student)=12
記憶體中的位元組對齊
一 什麼是位元組對齊,為什麼要對齊?現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定型別變數的時候經常在特定的記憶體位址訪問,這就需要各種型別資料按照一定的規則在空間上排列,而不是順序的乙個接乙個的排放,這就是對齊。對齊的作...
C 記憶體的位元組對齊
在訪問記憶體時,如果位址是按4位元組對齊,則訪問效率會高很多。這種現象的原因在於訪問記憶體的硬體電路。一般情況下,位址匯流排總是按照對齊後的位址來訪問。例如,你想得到0x00000001開始的四位元組內容,系統首先需要以0x00000000讀四位元組,從中取得3位元組,然後再用0x00000004作...
C語言 位元組對齊(記憶體對齊)
1 平台原因 移植原因 不是所有的硬體平台都能訪問任意位址上的任意資料,某些硬體平台只能在某些位址處取某些特定型別的資料,否則丟擲硬體異常 2 硬體原因 經過記憶體對齊之後,cpu的記憶體訪問速度大大提公升。1.對齊原則 原則1 資料成員對齊規則 結構 struct 或聯合 union 的資料成員,...