對於讀取資料流時(如網路或檔案)要特別注意。
比如
PBYTE pData;
//指向接收到的資料流
int * pi = pData + 這次接收到資料流的大小 - 4;
//指向接收到資料流的最後4位,可能客戶端發過來的這個資料流最後4位是int,那樣就是對齊好的了。也有可能不是int。
if *pi = 4561321 endparse data;//判斷作為資料流的結束標誌,最後4位的前面可能是全是char的。
由於這最後4位可能不是int,那樣就有可能不對齊,這裡就會出現Datatype misalignment錯誤。但是我們還是必須透過最後4位作為結束標誌,而只有知道什麼時候結束才能用int指標指向最後4位才不會出現對齊錯誤。這樣形成了一個死迴圈,難道沒辦法解決了麼?
PBYTE * pi = pData + 這次接收到資料流的大小 - 4;
int i;
memcpy(&i, pi, 4);
if i = 4561321 endparse data;
這樣就可以解決用int* pi指向未對齊的int錯誤了。
這一招對所有碰到Datatype misalignment的資料的訪問應該都有效,就是把Datatype misalignment的資料用memcpy複製到對齊的記憶體來訪問。
1,解析資料流時應該時刻注意。如果需要把一個數據流(BUFFER)轉化成結構進行取值,就應該把這個結構定義為按位元組存取.考慮如下結構:
struct a{
char a;
short b;
long c;
};
如果某個資料流中包含這樣的結構,而且我們要直接將資料流的指標轉化成該結構的指標,然後直接取結構成員的值,我們就應該將這個結構定義成按位元組訪問,即將其夾在語句
#pragma pack(push,1)//設為1位元組對齊
...
#pragma pack(pop)//還原為原來的位元組對齊方式
之中。如果我們不這樣做,編譯器會將成員b的地址對齊到short指標的地址,即在a之後加上一個char即8位的成員,將C對齊到LONG,即在B之後再加一個char成員。如此一來,成員B和成員C就得不到正確的值了。
pragma pack 只作用於結構的定義,而不是分配記憶體空間。把一個結構定義為pack1後,這個結構在程式中就一直是1了。
上面這個例子是客戶端傳送3個連續的資料不是傳送結構體,服務端接收結構體。
如果客戶端也傳送結構體,服務端也接收結構體就不需要這樣了。但是前提是雙方的對齊方式一致。所以在客戶端傳送前也要用#pragma pack()一下,服務端也要#pragma pack()一下。
最好還是客戶端也單個數據傳送,服務端也單個數據接收。
如果我們定義一個普通的結構用來存放一些資料,則不用定義成按位元組存取,編譯器會加上一些佔位成員,但並不會影響程式的執行。從這個意義上講,在ARM中,將結構成員定義成CHAR和SHORT來節約記憶體是沒有意義的。
一個典型的例子就檔案系統的驅動程式,檔案是以一些已經定義好的結構存放在儲存介質上的,它們被讀取到一個BUFFER中,而具體取某個檔案、目錄結構時,我們會將地址轉化成結構而讀取其中的值。
2,訪問外設時。
例如,磁碟驅動通常以16BIT的方式存取資料,即每次存取兩個位元組,這樣就要求傳給它的BUFFER是雙位元組對齊的,驅動程式應該至上層傳來的指標做出正確的處理以保證資料的正確性。
3.有時,我們沒有將資料流指標轉化為結構指標取值,但如果我們讀取的是雙位元組或者是四位元組的資料,同樣需要注意對齊的問題,例如,如果從一個BUFFER的偏移10處讀取一個四位元組值,則實際得到的值是偏移8處的
地址上的DWORD值。
對於讀取資料流時(如網路或檔案)要特別注意。
比如
PBYTE pData;
//指向接收到的資料流
int * pi = pData + 這次接收到資料流的大小 - 4;
//指向接收到資料流的最後4位,可能客戶端發過來的這個資料流最後4位是int,那樣就是對齊好的了。也有可能不是int。
if *pi = 4561321 endparse data;//判斷作為資料流的結束標誌,最後4位的前面可能是全是char的。
由於這最後4位可能不是int,那樣就有可能不對齊,這裡就會出現Datatype misalignment錯誤。但是我們還是必須透過最後4位作為結束標誌,而只有知道什麼時候結束才能用int指標指向最後4位才不會出現對齊錯誤。這樣形成了一個死迴圈,難道沒辦法解決了麼?
PBYTE pData;
PBYTE * pi = pData + 這次接收到資料流的大小 - 4;
int i;
memcpy(&i, pi, 4);
if i = 4561321 endparse data;
這樣就可以解決用int* pi指向未對齊的int錯誤了。
這一招對所有碰到Datatype misalignment的資料的訪問應該都有效,就是把Datatype misalignment的資料用memcpy複製到對齊的記憶體來訪問。
1,解析資料流時應該時刻注意。如果需要把一個數據流(BUFFER)轉化成結構進行取值,就應該把這個結構定義為按位元組存取.考慮如下結構:
struct a{
char a;
short b;
long c;
};
如果某個資料流中包含這樣的結構,而且我們要直接將資料流的指標轉化成該結構的指標,然後直接取結構成員的值,我們就應該將這個結構定義成按位元組訪問,即將其夾在語句
#pragma pack(push,1)//設為1位元組對齊
...
#pragma pack(pop)//還原為原來的位元組對齊方式
之中。如果我們不這樣做,編譯器會將成員b的地址對齊到short指標的地址,即在a之後加上一個char即8位的成員,將C對齊到LONG,即在B之後再加一個char成員。如此一來,成員B和成員C就得不到正確的值了。
pragma pack 只作用於結構的定義,而不是分配記憶體空間。把一個結構定義為pack1後,這個結構在程式中就一直是1了。
上面這個例子是客戶端傳送3個連續的資料不是傳送結構體,服務端接收結構體。
如果客戶端也傳送結構體,服務端也接收結構體就不需要這樣了。但是前提是雙方的對齊方式一致。所以在客戶端傳送前也要用#pragma pack()一下,服務端也要#pragma pack()一下。
最好還是客戶端也單個數據傳送,服務端也單個數據接收。
如果我們定義一個普通的結構用來存放一些資料,則不用定義成按位元組存取,編譯器會加上一些佔位成員,但並不會影響程式的執行。從這個意義上講,在ARM中,將結構成員定義成CHAR和SHORT來節約記憶體是沒有意義的。
一個典型的例子就檔案系統的驅動程式,檔案是以一些已經定義好的結構存放在儲存介質上的,它們被讀取到一個BUFFER中,而具體取某個檔案、目錄結構時,我們會將地址轉化成結構而讀取其中的值。
2,訪問外設時。
例如,磁碟驅動通常以16BIT的方式存取資料,即每次存取兩個位元組,這樣就要求傳給它的BUFFER是雙位元組對齊的,驅動程式應該至上層傳來的指標做出正確的處理以保證資料的正確性。
3.有時,我們沒有將資料流指標轉化為結構指標取值,但如果我們讀取的是雙位元組或者是四位元組的資料,同樣需要注意對齊的問題,例如,如果從一個BUFFER的偏移10處讀取一個四位元組值,則實際得到的值是偏移8處的
地址上的DWORD值。