在我的cpp实现中,我有:
static MyClass *instance;
在所有包含范围(卷曲{})之外自由浮动。我也尝试过将它初始化为nullptr。
void MyClass::myMethod() {
instance = this;
LOG("Hello, %d, %d", wList, instance->wList);
以上日志显示成员对象指针wList
的任意位置,但instance
应指向this
所执行的相同数据,因此wList
相同,但它并没有。 instance->wList
仍然是0.这里发生了什么?
答案 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位还是其他大小。这样做的一个不幸后果是确切的输出格式是实现定义的,这意味着它可以并且确实在系统之间发生变化。某些系统可能使用前导0x
或0X
,而其他系统可能根本没有前缀,只打印原始十六进制值。有些人可能会在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
两次转换的原因是为了避免虚假的编译器警告,因为如果从指针类型转换为整数类型并且保证不足以容纳指针,则某些编译器会抱怨。