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

assign `this` to `MyClass *instance`, `instance->member` is not referencing same memory as `this->member`

本文关键字:gt member 引用 内存 不同 this- instance- 分配 this MyClass instance      更新时间:2023-10-16

在我的cpp实现中,我有:

static MyClass *instance;

在所有包含作用域(大括号{})之外自由浮动。我也试过将它初始化为nullptr。

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

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

正如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,而其他系统可能根本没有前缀,只是打印原始十六进制值。

如果你想控制精确的输出,那么你可以使用你选择的格式(例如%08x%016llx),只要你为该说明符适当地转换指针。例如,以下是在32位和64位系统上的操作方法:

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

进行两次强制转换的原因是为了避免错误的编译器警告,因为如果从指针类型强制转换为不能保证大到足以容纳指针的整数类型,一些编译器会报错。

相关文章: