2010-10-11 118 views
0

當HWND位於布爾變量之前時,使用它們的內存位置訪問變量字段v2時出現錯誤值。如果在bool之後使用HWND,那麼我會得到正確的結果。使用實例變量(t)我得到正確的值爲v1v2,例如t->v1t->v2。我正在使用Windows Server 2003.我有以下測試類。這隻能在64位操作系統中重現; 32位操作系統工作正常。通過內存位置訪問變量

#include "conio.h" 
#include "stdio.h" 
include "windows.h" 
class Test 
{ 
public : 
Test() 
{ 
    v1=12345678; 
    v2=87654321; 
} 

HWND  hWnd; 
bool  MsgHandled; 



unsigned long v1; 
unsigned long v2; 

}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
Test* t=new Test(); 
unsigned long sign1 = *(unsigned long*)((unsigned char*)t + sizeof(Test)-2*sizeof(unsigned long)); 
unsigned long sign2 = *(unsigned long*)((unsigned char*)t + sizeof(Test)-sizeof(unsigned long)); 

printf("\nTest size %d",sizeof(Test)); 

printf("\n t->v1 %d",t->v1); 
printf("\n t->v2 %d",t->v2); 

printf("\n v 1 %d",sign1); 
printf("\n v 2 %d",sign2); // garbage value in 64 bit os 

getch(); 
return 0; 
} 

回答

2

你似乎認爲你v1v2必須在Test類型的對象末端精確駐留。這是完全沒有根據的假設。這種語言沒有這樣的保證,一般情況下他們不會。該對象通常以填充字節結束。這些填充字節是您實際在代碼中讀取的內容。難怪他們含有垃圾。

將填充字節添加到對象以滿足其對齊要求。由於在從32位模式切換到64位模式時,對齊要求可能(並且將會)發生改變,因此以不同模式編譯代碼時得到不同結果並不奇怪。

2

允許編譯器在任何地方添加填充以獲得最有效的地址和大小。它不能在POD結構中的第一個成員之前添加填充,普通的舊數據,但是你的類不是POD(它有一個構造函數)。你可以做些什麼來理解這個是去除構造函數 - 這樣你就有了POD - 並且使用標準庫的offsetof宏來檢查成員放置在結構中的哪個位置。

乾杯&心連心,

- 阿爾夫