(阅读文章之前,请先阅读本段。我要求对阅读这篇文章感兴趣的任何人都应尝试仔细阅读它,当然,除非您完全理解它,否则请不要对它投反对票,谢谢。)
现在是社区Wiki,因此,如果有人不同意任何概念,请对其进行修改,并清楚,详细地说明错误之处和原因,并尽可能引用源或提供可复制的证据。
回答
还有其他一些原因可能是NULL == 0的潜在因素
- 零是错误的事实,因此可以直接
if(!my_ptr)
代替if(my_ptr==NULL)
。
- 未初始化的全局整数默认情况下初始化为全零的事实,因此全零的指针将被视为未初始化。
在这里我想谈谈其他答案
不是因为语法糖
说NULL是因为语法糖,所以没有太大意义,如果是这样,为什么不使用数组的索引0来保持其长度呢?
实际上,C是与内部实现最相似的语言,说C仅仅因为语法糖就选择了零,是否有意义?他们宁愿提供关键字null(就像许多其他语言一样),而不是将零映射到NULL!
因此,到目前为止,它可能只是语法糖,很明显,C语言开发人员的初衷不是语法糖,正如我将进一步说明的那样。
1)规格
然而,虽然C规范确实从常量0说起了空指针(第6.3.2.3节),并且还定义了要实现的NULL定义(C11规范中的7.19和C99规范中的7.17),实际上,在5.4的发明人所写的“ C编程语言”一书中,有以下内容:
C保证零永远不会是数据的有效地址,因此零返回值可用于表示异常事件,在这种情况下,没有空间。
指针和整数不可互换,零是唯一的例外:常量零可以分配给指针,并且指针可以与常量零进行比较。符号常量NULL通常代替零,用作助记符,以更清楚地指示这是指针的特殊值。NULL在中定义。此后我们将使用NULL。
正如人们所看到的那样(从“零地址”开始),至少C语言作者的初衷是地址零,而不是常数零,而且从此摘录中可以看出,规范之所以从常量零可能不排除计算结果为零的表达式,而是包括整数常量零,这是唯一允许在不强制转换的情况下用于指针上下文的整数常量。
2)总结
尽管规范中并未明确指出零地址可以与零常量区别对待,但并未说明不能,并且在处理空指针常量时并未声明将其定义为实现。由NULL定义的常量进行运算,而不是声称它为零,这表明零常量和零地址之间可能存在差异。
(但是如果是这种情况,我只是想知道为什么要定义实现NULL,因为在这种情况下NULL也可以是常量零,因为编译器必须将所有零常量转换为实际的实现定义的NULL?)
但是,我在实际操作中看不到这一点,在通用平台中,地址零和常数零被视为相同,并抛出相同的错误消息。
此外,事实是,当今的操作系统实际上正在保留整个第一页(范围从0x0000到0xFFFF),只是为了防止由于C的NULL指针而访问零地址(请参见http://en.wikipedia.org/wiki/ Zero_page以及“ Jeffrey Richter和Christophe Nasarre的Windows Via C / C ++ Windows(由Microsoft Press出版)”。
因此,我会要求任何声称实际上已将其付诸实践的人要求指定平台和编译器以及他实际执行的确切代码(尽管由于规范中的定义含糊不清[正如我所展示的]任何编译器并且平台可以自由地做他想做的事情)。
但是,显然C的作者没有想到这一点,他们说的是“零地址”,并且“ C保证它永远不是有效地址”,以及“ NULL只是一个助记符”,清楚地表明它的初衷不是“语法糖”。
不是因为操作系统
还声称由于某些原因,操作系统拒绝访问地址零:
1)编写C时没有这种限制,就像在这个Wikipage上可以看到的那样:http://en.wikipedia.org/wiki/Zero_page。
2)事实是C编译器确实访问了内存地址零。
这是BellLabs(http://www.cs.bell-labs.com/who/dmr/primevalC.html)的以下论文中的事实。
两种编译器在处理方式上的细节不同。在较早的版本中,通过命名函数来找到起点。在后面的代码中,开始简单地设为0。这表明第一个编译器是在我们拥有内存映射的计算机之前编写的,因此程序的起始位置不在位置0,而在第二个位置,我们有一个确实提供映射的PDP-11。
(事实上,截至今天(正如我从Wikipedia和Microsoft Press引用的参考文献中所述),限制对零地址的访问的原因是由于C的NULL指针!因此最后,结果却是相反的!)
3)请记住,C也用于编写操作系统,甚至C编译器!
实际上,C是为了用它编写UNIX操作系统而开发的,因此,似乎没有理由说他们应该限制自己的地址为零。
关于计算机如何(物理上)能够访问地址零的(硬件)说明
我还要在这里解释另一点,怎么可能完全引用地址零?
想一想,地址由处理器获取,然后作为电压在内存总线上发送,然后由内存系统用于获取实际地址,但是地址为零将意味着没有电压,那么存储系统的物理硬件如何访问地址零?
答案似乎是,地址零是默认地址,换句话说,当内存总线完全断开时,内存系统始终可以访问地址零,因此任何不指定实际地址的读取或写入请求(地址为零的情况)自动访问地址零。
if (p != 0)
将if (p)
其更改为C和C ++中的常见用法,尽管如果您使用Java,则必须摆脱这种习惯。