程式语言中,空指标[1](英语:Null Pointer)是一个已宣告但并未指向一个有效物件的指标,许多程式利用空指标来表示某些特定条件,例如未知长度阵列的结尾或某些无法执行的操作。在可选择型态(optional type)的程式语言中,空指标通常可以跟可为Null的型别(Nullable types)和空值(Nothing value)进行比较。

空指标与未初始化的英语Uninitialized_variable指标(uninitialized pointer)不同,空指标保证不会和有值的指标相等,而未初始化的指标则是要看所使用的程式语言或编译器而定,在部分程式语言环境下,未初始化的指标无法保证不与有值的指标相等,他可能因为存有记忆体残值而指向了某个有效物件。有许多实现上是以0 (全位为0) 代表空指标。

空参照

程式语言中,空参照(英语:Null Reference)是一个与空指标类似的概念,是一个已宣告但其并未参照到一个有效物件的变数。东尼·霍尔在1965年发明了空参照,并作为ALGOL W程式语言的一部分[2]

历史

查尔斯·安东尼·理察·霍尔(C. A. R. Hoare)在2009年表示他在1965年发明了空参照,并且将这项发明描述为“十亿美元的错误”[2]

程式语言中的空指标

C语言

在C语言中,任何2个空指标都保证是相等的[4],其是由预处理器的巨集提供,即NULL,其被定义为用来表示空指标的常数值,在C99是透过隐含转换或直接转换成void*的整数值0来使用[5]

在C语言中,空指针的值表示为#define NULL (void *)0[6]

C语言标准并没有规定记忆体位置0与空指标相同,随然实际上记忆体位置0与空指标在大部分的情况下会是相同的。对空指标解引用在C语言中是一个未定义行为,在实作上,解引用时必须确保所取的指标不为空。

C++语言

C++语言中,同样有继承自C语言的NULL巨集可供使用,但在传统上会优先使用整数零来表示空指标常数[7]。在C++11标准中已明确的引入一个常数(部分编译器视之为关键字,如Visual Studio)nullptr做为表示空指标的常数[8]

nullptr是C++11语言中的关键字,在C++11语言标准用来表示空指标的常数值。其型态为nullptr_t[8]

其他语言

一些语言使用其他的命名方式来表示空指针,如Pascal, Ruby 以及 Lua 则使用 nil[9]Visual Basic 使用 NothingFortran不支持此一常量,但其属性(property)可被设置成 NULLIFY 并由 ASSOCIATED 函数测试之。

解引用

因为空指标没有指向有效的物件,所以若尝试解引用(Dereference,即,从该记忆体位置取出数值)的话,有机率导致程式执行时发生错误或立即崩溃。

  • 在C语言中,对空指标解引用是一个未定义行为。许多实作对空指标解引用的案例都会导致程式因为segmentation fault而当机或停止运作,因为空指标通常表示选择了一个不是由系统分配的储存空间,但是并非每次都会出现这种情况。
  • 在Java语言中,若尝试从空指标的物件中解引用则会触发NullPointerException(NPE)[10],由于会触发错误,因此可以使用例外处理的程式码来捕捉,但编程上仍要尽量确保永远不会发生此错误为佳。

NullPointerException

空指标错误是一种常见的程式错误,当尝试存取空指标所指向之物件时,就会发生NullPointerException[11],通常是因为物件未顺利初始化或者提前解构而造成。空指标错误常常出现在类别设计或管理上有缺陷的程式中,一旦出现了空指标错误经常会导致程式当机或崩溃[12]。而在部分程式语言中,则有NullReferenceException[13](空参照错误),例如.Net平台。

在Java中,NullPointerException被定义在java.lang.NullPointerException日语NullPointerException,是一种执行阶段错误(java.lang.RuntimeException)。

参见

参考文献

  1. ^ 空指標 null pointer. 国家教育研究院. [2018-09-08]. (原始内容存档于2018-09-09). 
  2. ^ 2.0 2.1 Tony Hoare. Null References: The Billion Dollar Mistake. InfoQ.com. 2009-08-25 [2018-09-08]. (原始内容存档于2018-09-04). 
  3. ^ 3.0 3.1 Joint Technical Committee ISO/IEC JTC 1, Subcommittee SC 22, Working Group WG 14. International Standard ISO/IEC 9899 (PDF; Committee Draft). 2007-09-08 [2018-09-08]. (原始内容存档 (PDF)于2018-06-24). 
  4. ^ ISO/IEC 9899[3], clause 6.3.2.3, paragraph 4.
  5. ^ ISO/IEC 9899[3], clause 7.17, paragraph 3: NULL... which expands to an implementation-defined null pointer constant...
  6. ^ NULL pointer in C. [2018-09-09]. (原始内容存档于2018-09-09). 
  7. ^ Stroustrup, Bjarne. Chapter 5: Pointers, Arrays, and Structures: 5.1.1: Zero. The C++ Programming Language 14th printing of 3rd. United States and Canada: Addison–Wesley. March 2001: 88. ISBN 0-201-88954-4. In C, it has been popular to define a macro NULL to represent the zero pointer. Because of C++'s tighter type checking, the use of plain 0, rather than any suggested NULL macro, leads to fewer problems. If you feel you must define NULL. use
        const int NULL = 0;
    The const qualifier (§5.4) prevents accidental redefinition of NULL and ensures that NULL can be used where a constant is required.
     
  8. ^ 8.0 8.1 A name for the null pointer: nullptr (PDF). stroustrup.com. 2003-09-10 [2018-09-09]. (原始内容 (PDF)存档于2017-07-05). 
  9. ^ Elliot B. Koffman, Pascal 3rd Edition, Addison Wesley, Reading MA, ISBN 0-201-11834-3, pp. 678-679
  10. ^ java.lang.NullPointerException. docs.oracle.com. [2018-09-08]. (原始内容存档于2018-09-10). 
  11. ^ Null pointer exceptions. 曼彻斯特大学电脑科学系. [2018-09-09]. (原始内容存档于2018-03-25). 
  12. ^ 新版Android SDK寬容處理Kotlin程式碼可空合約違規,給開發者更新的緩衝時間. ithome.com.tw. [2018-09-08]. (原始内容存档于2018-09-09). 
  13. ^ System.NullReferenceException. msdn.microsoft.com. [2018-09-08]. (原始内容存档于2018-09-09).