指针上下文中的常量 0 何时获得其特殊地位?
如您所知,在标准现代 C 语言中,指针上下文中使用的常量 0 值充当空指针常量,它被转换为特定于平台的(甚至可能特定于类型的) >空指针值。
同时,C 语言的早期版本,如 C 中所述参考手册,没有对指针和整数上下文做出太多区分,允许人们自由地比较整数并将其分配给指针。如果我没记错的话,在那个版本的 C 中,常量 0 没有特殊地位,这意味着将常量 0 的值分配给指针只会使其指向物理地址 0(就像将值 42 分配给指针一样)使其指向物理地址42)。
在 ANSI C 中,情况发生了显着变化。现在,将常量 0 分配给指针会将一些特定于平台的空指针值放入该指针中。空指针值不需要用物理0值来表示。
那么,在 C 语言历史上的哪个时刻,它从一种语言转变为另一种语言呢?鉴于空指针的特殊地位,K&RC 是否已经融入了常量 0 的更高级别的概念?或者即使对于常量 0,K&RC 仍然保证整数物理分配给指针吗?
As you know, in standard modern C language the constant 0 value used in pointer context acts as a null-pointer constant, which gets converted to a platform-specific (and possibly even type-specific) null-pointer value.
Meanwhile, the early versions of C language, as the one described in C Reference Manual, did not make much of a distinction between pointer and integer contexts, allowing one to freely compare and assign integers to pointers. If am not mistaken, in that version of C the constant 0 had no special status, meaning that assigning the value of constant 0 to a pointer would simply make it point to physical address 0 (just like assigning the value of 42 to a pointer would make it point to physical address 42).
In ANSI C things have changed significantly. Now assigning the constant 0 to a pointer will place some platform-specific null-pointer value into that pointer. Null-pointer value is not required to be represented by physical 0 value.
So, at what point in the history of C language did it change from one to another? Did K&R C already incorporate the higher-level concept of null-pointer with constant 0 given its special status? Or did the K&R C still guarantee physical assignment of integers to pointers even for constant 0?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
它可以追溯到几乎 C 的开头(如果不是最开始的话)。如果您查看1974 年 1 月 C 参考手册的第 21 页,您会发现更多内容或者在一些示例代码中不太直接说明:
再进一步返回到 ca。 1972-73 PDP-11/20 编译器,我们发现:
至少如果我正确阅读的话,
if (tree==0)
行正在检查tree
在尝试取消引用之前是一个非空指针。不幸的是,丹尼斯说他对日期的确定程度比“1972-73”。
在此之前,C 语言的历史并不多。尽管如此,似乎确实有一些 0 被视为空指针的历史。在我看来,使用 0 作为空指针是 C 从 Unix“继承”的。 1971 年 11 月 1 日的
exec
条目版Unix程序员手册显示了一个值为0的指针来表示参数列表的结尾。根据Dennis的描述,此时“C还没有到来。 ”基于所有这些,我初步得出结论,C 从一开始就将 0 视为空指针,或者至少很早就将 0 视为空指针,以至于可能不再有任何该语言版本的记录。
我在追踪有关空指针可能具有非零位的第一个点的文档方面还没有那么成功。从语言的角度来看,这从来都是相关的。我怀疑这件事发生得很早,但找到支持这一点的文档会很困难。 C 最早的移植之一是 IBM System/360 大型机,尽管我找不到直接记录它,我的猜测是这些机器上使用的内部空指针值可能非零。我手边没有确切的数字,但我知道这些机器上的 PL/I 使用非零值来相当于空指针;我猜测当他们将C移植到这些机器时,他们可能使用了相同的值。
It goes back to nearly the beginning of C (if not the very beginning). If you look on page 21 of the January 1974 C reference manual, it's more or less directly stated in some sample code:
Going back still a bit further, to ca. 1972-73 PDP-11/20 compiler, we find:
At least if I'm reading this correctly, the
if (tree==0)
line is checking thattree
is a non-null pointer before attempting to dereference it.Unfortunately, Dennis says he can't be much more certain about the date than "1972-73".
There isn't much history of C before that. Nonetheless, there does seem to be a bit of history of 0 being treated as a null pointer. It looks to me like use of 0 as a null pointer is something that C "inherited" from Unix. The entry for
exec
in the November 1971 1st Edition Unix programmer's manual shows a pointer with the value 0 to signal the end of the list of arguments. According to Dennis' description, at this point "C was still to come."Based on all this, I'd tentatively conclude that C treated 0 as a null pointer from the very beginning, or at least so early on that there's probably no longer any record of a version of the language that was otherwise.
I haven't been nearly as successful at tracking down documentation about the first point at which a null pointer might have had non-zero bits. From the viewpoint of the language, this has never been relevant. I suspect it happened fairly early on, but finding documentation to support that would be difficult. One of the earliest ports of C was to IBM System/360 mainframes, and although I can't find direct documentation of it, my guess would be that internally the null pointer value used on these machines was probably non-zero. I don't have the exact number handy, but I know that PL/I on these machines used a non-zero value for its equivalent of a null pointer; I'd guess that when they ported C to these machines, they probably used the same value.
请参阅 C-faq 问题 5.4
作为一种风格问题,许多程序员不喜欢未经修饰的 0 分散在他们的程序中,一些代表数字,一些代表指针。因此,预处理器宏 NULL 被定义(由多个头文件,包括 和 )作为空指针常量,通常为 0 或 ((void *)0)(另请参见问题 5.6)。希望明确区分整数 0 和空指针常量 0 的程序员可以在需要空指针时使用 NULL。
使用 NULL 只是一种风格约定;预处理器将 NULL 返回为 0,然后编译器在指针上下文中像以前一样识别它。特别是,在函数调用参数中的 NULL 之前(如 0 之前)可能仍然需要进行强制转换。上面问题 5.2 下的表适用于 NULL 和 0(未修饰的 NULL 相当于未修饰的 0)。
NULL 只能用作指针常量;见问题 5.9。
这个臭名昭著的空指针到底是什么?
语言定义指出对于每种指针类型,都有一个特殊的值——“空指针”——它与所有其他指针值不同,并且“保证与任何对象或函数的指针比较不相等”。也就是说,空指针绝对指向任何地方;它不是任何对象或函数的地址。运算符的地址 &永远不会产生空指针,也不会成功调用 malloc。[脚注](malloc 失败时确实会返回空指针,这是空指针的典型用法:作为具有其他含义的“特殊”指针值,通常是“未分配”或“尚未指向任何地方。”)
空指针在概念上与未初始化的指针不同。已知空指针不指向任何对象或函数;未初始化的指针可能指向任何地方。另请参见问题 1.30、7.1 和 7.31。
如上所述,每种指针类型都有一个空指针,不同类型的空指针内部值可能不同。尽管程序员不需要知道内部值,但必须始终告知编译器需要哪种类型的空指针,以便在必要时进行区分(参见问题 5.2、5.5 和 5.6)。
最后,只有值为 0 的常量整数表达式才能保证指示空指针。
See the C-faq question 5.4
As a matter of style, many programmers prefer not to have unadorned 0's scattered through their programs, some representing numbers and some representing pointers. Therefore, the preprocessor macro NULL is defined (by several headers, including and ) as a null pointer constant, typically 0 or ((void *)0) (see also question 5.6). A programmer who wishes to make explicit the distinction between 0 the integer and 0 the null pointer constant can then use NULL whenever a null pointer is required.
Using NULL is a stylistic convention only; the preprocessor turns NULL back into 0 which is then recognized by the compiler, in pointer contexts, as before. In particular, a cast may still be necessary before NULL (as before 0) in a function call argument. The table under question 5.2 above applies for NULL as well as 0 (an unadorned NULL is equivalent to an unadorned 0).
NULL should be used only as a pointer constant; see question 5.9.
What is this infamous null pointer anyways?
The language definition states that for each pointer type, there is a special value--the "null pointer"--which is distinguishable from all other pointer values and which is "guaranteed to compare unequal to a pointer to any object or function." That is, a null pointer points definitively nowhere; it is not the address of any object or function. The address-of operator & will never yield a null pointer, nor will a successful call to malloc.[footnote] (malloc does return a null pointer when it fails, and this is a typical use of null pointers: as a "special" pointer value with some other meaning, usually "not allocated" or "not pointing anywhere yet.")
A null pointer is conceptually different from an uninitialized pointer. A null pointer is known not to point to any object or function; an uninitialized pointer might point anywhere. See also questions 1.30, 7.1, and 7.31.
As mentioned above, there is a null pointer for each pointer type, and the internal values of null pointers for different types may be different. Although programmers need not know the internal values, the compiler must always be informed which type of null pointer is required, so that it can make the distinction if necessary (see questions 5.2, 5.5, and 5.6).
Finally, only constant integral expressions with value 0 are guaranteed to indicate null pointers.