将`this`分配给`MyClass * instance`,`instance-> member`不引用与`this-> member`相同的内存

时间:2014-07-27 01:54:38

标签: c++

在我的cpp实现中,我有:

static MyClass *instance;

在所有包含范围(卷曲{})之外自由浮动。我也尝试过将它初始化为nullptr。

void MyClass::myMethod() {
 instance = this;
 LOG("Hello, %d, %d", wList, instance->wList);

以上日志显示成员对象指针wList的任意位置,但instance应指向this所执行的相同数据,因此wList相同,但它并没有。 instance->wList仍然是0.这里发生了什么?

1 个答案:

答案 0 :(得分:3)

正如Mark Ransom在评论中指出的那样,您无法使用%d格式说明符来打印指针,您必须使用%p才能使代码可移植。技术上未定义的行为可以使用除%p之外的任何内容来指示,但很可能您会发现它在32位系统上似乎正常工作。

然而,在64位系统上,我打赌你正在使用它,它会爆炸。指针是8个字节,但printf仅在尝试%d时尝试读取堆栈的4个字节。对于第二个%d说明符,它读取接下来的4个字节,这是指针的另外4个字节 - 如果您为此看到0,则可能意味着您的指针在前4个字节内被分配小端系统上的GB内存(即它的值类似于0x00000000'xxxxxxxx)。传递给printf的第二个指针的堆栈上的8个字节永远不会被读取。

%p说明符在所有平台上都可以移植地打印指针,无论它们是32位,64位还是其他大小。这样做的一个不幸后果是确切的输出格式是实现定义的,这意味着它可以并且确实在系统之间发生变化。某些系统可能使用前导0x0X,而其他系统可能根本没有前缀,只打印原始十六进制值。有些人可能会在0左右填充左侧,而其他人可能不会填充。

如果您想控制确切的输出,那么您可以使用您选择的格式(例如%08x%016llx,只要您为该说明符适当地转换指针< / em>的。例如,以下是如何在32位和64位系统上执行此操作:

printf("0x%08x\n", (unsigned int)(uintptr_t)myPointer);           // 32-bit
printf("0x%016llx\n", (unsigned long long)(uintptr_t)myPointer);  // 64-bit

两次转换的原因是为了避免虚假的编译器警告,因为如果从指针类型转换为整数类型并且保证不足以容纳指针,则某些编译器会抱怨。