将NULL分配给x64指针

assigning NULL to x64 pointers

本文关键字:x64 指针 分配 NULL      更新时间:2023-10-16

我有一个在x86平台上运行良好的进程
现在我把它编译成x64,突然间我不能给指针分配NULL
如果我这样做:

void* pointy = NULL;

它将指向0x0000000100000000
怎么回事?

Null不一定是逐位零。它的价值是由实现定义的。


也就是说,这些都是一样的:

void* pointy = NULL;
void* pointy = 0;
void* pointy = nullptr;

它们将空指针值分配给pointy。这个值在比特级别上是什么是完全未指定的,并且不一定所有比特都为零!

如果你的代码是你说的那样,那么要么:你的平台确实使用了null的值,它没有,你的编译器坏了,要么它没有,而且你读错了值。

在任何情况下,C++代码都是好的,并将pointy设置为null。无需再担心任何事情。

当您执行包含以下内容的程序时:

void* pointy = NULL;

它初始化指针对象pointy,使其包含空指针值(假设您有#include d定义NULL宏的一个标头)。

空指针是给定指针类型的值,与该类型的任何其他值都不同。从逻辑上讲,它是一个不指向任何东西的指针。

空指针可以在C++源代码中用空指针常量表示。NULL是一个扩展为空指针常量的宏。文字0也是一个空指针常量,关键字nullptr(该语言的最新添加)也是如此。这并不意味着一定意味着空指针值表示为所有位零,但它通常是,我愿意打赌它在您的系统上。

如果打印pointy:的值

std::cout << "pointy = " << pointy << "n";

您将看到一个空指针的实现定义表示。在我的系统上,它打印pointy = 0。在其他系统上,它可能是0x0[null],或者几乎是其他任何东西,但它应该可以识别为空指针。

要测试pointy的值是否为空指针,请在程序中进行比较:

if (pointy == NULL) {
    std::cout << "Yes, it's a null pointern");
}
else {
    std::cout << "No, it's not a null pointer (?)n");
}

请注意,您不能取消引用pointy来确定它指向什么,因为它的类型是void*。如果它是其他指针类型,例如int*,那么您可以编写代码来取消引用它,但该代码的行为是未定义的;最有可能的行为是程序崩溃,但一切皆有可能。

至于您在调试器中看到的内容,如果没有更多信息,我真的无法猜测。调试器可能工作不正常,但这种可能性不大。您可能正在查看pointy指向的内容(可能位于内存地址0),但这也不太可能;由于void*指针不指向任何指定类型的数据,因此调试器无法显示它

可能是您在pointy的定义中设置了一个断点,并在遇到断点时查看其中存储的值吗?如果是这样的话,您可能只是在初始化发生之前看到了值。试着向前走一行,再看一次数值。如果这似乎在x86上正常工作,那可能是因为pointy在初始化之前包含的垃圾看起来像一个空指针。

在任何情况下,C++语言都不会说明在使用调试器时会看到什么;它只定义程序执行时的行为。如果您在使用调试器时遇到问题,这是一个合理的问题,但您需要告诉我们您正在使用什么调试器,确切地说您正在使用它做什么,并向我们展示一个显示问题的完整小程序。

编辑:在对另一个答案的评论中,您写了

我希望"pointy"指向0。

至少有两件非常不同的事情可能意味着。

此:

int* ptr = new int(0);

使CCD_ 21指向存储器中某个地方的对象;该对象包含CCD_ 22值CCD_。你可以说"ptr指向0",但更准确的说法是"ptr指的是一个值为0的对象"。

此:

int *nptr = 0;

导致nptr的值为空指针。这可能就是您所说的"指向0"的意思,但最好说nptr的值是一个空指针。(如果将nptr视为机器级地址,则它可能包含内存位置0的地址;换句话说,nptr指向内存位置0。但用C++的术语来说,它根本没有真正指向任何内存位置;空指针值是一个类似地址的特殊值,用于区分不指向任何位置的指针和指向对象的指针。)

我认为,您真正想要的是pointy包含一个空指针值,以及您向我们展示的代码:

void* pointy = NULL;  // or 0, or nullptr

正是正确的方法。