通过内存位置访问变量

时间:2010-10-11 06:27:02

标签: c++

当HWND在bool变量之前时,当使用其内存位置访问变量v2时,我得到错误的值。如果我在bool之后使用HWND,那么我得到正确的结果。使用实例变量(t),我得到v1v2的正确值,例如t->v1t->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;
}

2 个答案:

答案 0 :(得分:2)

您似乎认为您的v1v2必须恰好位于Test类型对象的末尾。这是一个完全没有根据的假设。该语言没有这样的保证,一般情况下他们不会。该对象通常以填充字节结束。这些填充字节是您在代码中实际读取的内容。难怪它们含有垃圾。

填充字节被添加到对象以满足其对齐要求。由于在从32位模式切换到64位模式时,对齐要求可以(并且将会)发生变化,因此在以不同模式编译代码时获得不同结果也就不足为奇了。

答案 1 :(得分:2)

允许编译器在任何地方添加填充,以获得最有效的地址和大小。它不能在POD结构中的第一个成员之前添加填充,普通旧数据,但是您的类不是POD(它有一个构造函数)。您可以做的是要删除构造函数 - 以便您拥有POD - 并使用标准库的offsetof宏来检查成员在结构中的确切位置。

干杯&第h。,

- Alf