6.6 The Null Pointer
The Standard defines a NULL pointer as a pointer value that does not point to anything at all. To make a pointer variable NULL you assign it the value zero, and to test whether a pointer variable is NULL you compare it to zero. The choice of the value zero is a source code convention; internally, the value for a NULL pointer might actually be something different. In this case, the compiler takes care of translating between zero and the internal value.
标准定义了NULL 指针,它作为一个特殊的指针变量,表示不指向任何东西。要使→个指针变量为NULL ,你可以给它赋-个零值。为了测试一个指针变量是否为NULL.你可以将它与零值进行比较。之所以选择零这个值是因为一种源代码约定。就机器内部而言, NULL 指针的实际值可能与此不同。在这种情况下,编译器将负责零值和内部值之间的翻译转换。
The concept of a NULL pointer is quite useful because it gives you a way to specify that a particular pointer is not currently pointing to anything at all. For example, a function whose job is to search an array for a specific value may return a pointer to the array element that was found. If no element in the array contained the right value, a NULL pointer could be returned instead. This technique allows the return value to convey two different pieces of information. First, was an element found?Second, if an element was found, which one was it?
NULL 指针的概念是非常有用的,因为它给了你-种方法,表示某个特定的指针目前并未指向任何东西。例如,一个用于在某个数组中查找某个特定值的函数可能返回一个指向查找到的数组元素的指针。如果该数组不包含指定条件的值,函数就返回一个NulL 指针。这个技巧允许返回值传达两个不同片段的信息。首先,有没有找到元素?其次,如果找到,它是哪个元素?
Although this technique is commonly used in C programs, it violates a software engineering principle. It is risky for a single value to have two different meanings because it is easy to be confused later on as to which meaning is actually intended.This problem is more serious in larger programs because it is impossible to keep the entire design in your head at once. A safer strategy is to have the function return two separate values: the first is a status value indicating the result of the operations, and the second is the pointer, which is used only when the status indicates that a match was found.
尽管这个技巧在C 程序中极为常用,但它违背了软件工程的原则。用一个单一的值表示两种不同的意思是件危险的事,因为将来很容易无法弄清哪个才是它真正的用意。在大型的程序中,这个问题更为严重,因为你不可能在头脑中对整个设计一览无余。一种更为安全的策略是让函数返回两个独立的值:首先是个状态值,用于提示查找是否成功;其次是个指针,当状态值提示查找成功时,它所指向的就是查找到的元素。
Dereferencing a pointer gives you the value to which it points. But the null pointer, by definition, points to nothing at all. Therefore, it is illegal to dereference a NULL pointer. Before dereferencing a pointer, you must first make sure that it is not NULL.
对指针进行解引用操作可以获得它所指向的值。但从定义上看, NULL 指针并未指向任何东西。因此,对-个NULL 指针进行解引用操作是非法的。在对指针进行解引用操作之前,你首先必须确保它并非NULL 指针。
What happens if indirection is performed on a NULL pointer? The result is implementation dependent. On some machines, the indirection accesses memory location zero. The compiler ensures that there arenʹt any variables stored at location zero, but the machine doesnʹt prevent you from accessing or modifying the location.This behavior is very unfortunate, because the program contains an error but the machine hides its symptoms, thus making the error more difficult to find.
如果对一个NULL 指针进行间接访问会发生什么情况呢?它的结果因编译器而异。在有些机器上,它会访问内存位直零。编译器能够确保内存位直零没有存储任何变量,但机器并未妨碍你访问或修改这个位直。这种行为是非常不幸的,因为程序包含了一个错误,但机器却隐匿了它的症状,这样就使这个错误史加难以寻找。
On other machines, indirection on a NULL pointer causes a fault that terminates the program. It is much better to announce that an error was discovered than to hide it, because the programmer can then correct it more easily.
在其他,机器上,对NULL 指针进行间接访问将引发一个错误,并终止程序。宣布这个错误比隐藏这个错误要好得多,因为程序员能够更容易修正它。
It would be nice if all pointer variables, not just those in static memory, were automatically initialized to NULL, but they are not. No matter how your machine handles dereferencing a NULL pointer, it is a good idea to explicitly initialize all your pointer variables. Use the desired address if it is known, otherwise initialize them to NULL. In well‐written programs that check pointers before dereferencing them, this initialization can save you a lot of debugging time.
如果所有的指针变量(而不仅仅是位于静态内存中的指针变量)能够被自动初始化为NULL ,那实在是件幸事,但事实并非如此。不论你的机器对解引用NULL 指针这种行为作何反应,对所有的指针变量进行显式的初始化是种好做法。如果你已经知道指针将被初始化为什么地址,就把它初始化为该地址,否则就把它初始化为NULL。风格良好的程序会在指针解引用之前对它进行检查,这种初始化策略可以节省大量的调试时间。