当HWND在bool变量之前时,当使用其内存位置访问变量v2
时,我得到错误的值。如果我在bool之后使用HWND,那么我得到正确的结果。使用实例变量(t
),我得到v1
和v2
的正确值,例如t->v1
和t->v2
。我使用的是Windows Server 2003.我有以下Test类。这只能在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;
}
答案 0 :(得分:2)
您似乎认为您的v1
和v2
必须恰好位于Test
类型对象的末尾。这是一个完全没有根据的假设。该语言没有这样的保证,一般情况下他们不会。该对象通常以填充字节结束。这些填充字节是您在代码中实际读取的内容。难怪它们含有垃圾。
填充字节被添加到对象以满足其对齐要求。由于在从32位模式切换到64位模式时,对齐要求可以(并且将会)发生变化,因此在以不同模式编译代码时获得不同结果也就不足为奇了。
答案 1 :(得分:2)
允许编译器在任何地方添加填充,以获得最有效的地址和大小。它不能在POD结构中的第一个成员之前添加填充,普通旧数据,但是您的类不是POD(它有一个构造函数)。您可以做的是要删除构造函数 - 以便您拥有POD - 并使用标准库的offsetof
宏来检查成员在结构中的确切位置。
干杯&第h。,
- Alf