取消引用NULL指针是否保证在C / C ++中崩溃程序?

我遇到了这个有线代码而且没有崩溃。

#include  struct s { char* c; char* c2; }; int main() { struct s* p = NULL; printf("%d\n", &(p->c)); printf("%d\n", &p->c2); printf("%d\n", &(*p).c2); return 0; } 

输出:

 0 4 4 

我有几个问题来找我,我无法回答:

  1. 在c / c ++中,NULL指针总是等于0吗?

  2. 如果0恰好是变量的地址会发生什么?

  3. 输出似乎是结构成员的偏移地址。 这是如何计算的。 我的意思是p-> c是c的地址,它不存在,因为p == NULL。 如果c的地址不存在,为什么你可以通过&p-> c得到地址c?

  4. 取消引用NULL指针是否保证在C / C ++中使程序崩溃?(让我们假设在系统中)

不,取消引用空指针不能保证崩溃。

首先,在许多情况下,编译器能够优化解除引用操作。 在您的情况下, &(p->c)名义上取消引用空指针,但是然后获取结果的地址(在选择指向结构的成员之后)。 据推测,编译器用数字替换整个表达式,数字是结构中成员的偏移量。 (不能保证空指针指向地址0,或者它将以这种方式进行优化,但它恰好在您的系统上执行。)

这是标准offsetof宏的通用实现的基础。 它不能在便携式标准C或C ++中实现,但实现通常使用这样的系统特定技巧 – 只要它在该系统上产生正确的结果它就完全有效。

其次,即使您实际取消引用空指针,行为也是未定义的 。 这可能意味着你的程序崩溃,但就语言标准而言,它可以做任何事情。

过去有一些系统(可能还有),其中空指针指向地址0,并且系统的存储器映射被设置为使得地址0是恰好包含0值的有效存储器地址。 例如,在这样的机器上,空指针就像一个指向空'\0'终止字符串的指针。 当在这样的系统上工作的代码无意中依赖于该行为时,这导致了一系列错误修复,并被移植到具有更强内存保护的新系统。 (我认为这可能是从基于68K的Sun 3过渡到基于SPARC的Sun 4,但我不确定。)

有关空指针的更多信息,请参阅comp.lang.c FAQ的第5节。 其中大部分也适用于C ++。

您实际上并没有取消引用指针。 这就是代码没有崩溃的原因。 代码的作用是获取struct成员的偏移量。 第一个成员的偏移量为0字节,第二个成员的长度为4个字节。

c标准不保证NULL指针定义为0,它是实现定义的。 (201x:7.19)

在C ++中,空指针始终为0。

在C中,NULL指针可能不是0,但我从未见过这样的系统。

在所有使用虚拟内存的现代系统中,取消引用空指针都会崩溃。 但你没有在你的BTW计划中这样做。

  1. NULL始终为零: http : //www.cplusplus.com/reference/cstring/NULL/ 。

空指针常量是一个整数常量表达式,其计算结果为零(如0或0L),或者将此类值转换为void *(如(void *)0)。

2.这非常不可能,部分原因是虚拟内存,并且可能在编译器中被阻止。 3.编译器可能会实现具有偏移量的结构。 此外,您不是取消引用指针,只取地址。

  1. 当然,NULL始终为0.除非您将其定义为其他内容。
  2. 我认为现在不允许将页面映射为0,但如果允许,则可以在地址0处有一个变量。
  3. 你看,你从未真正访问过p指向的变量。 你只想要他们的地址。 它们可以从p计算出来。 一个指针需要4个字节(在你的平台上),所以我们知道结构偏移中的第一个指针是0,第二个是4,等等。