From bdf0e899a7f9619acba31f8c5eee15bb2d6c6324 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 21 May 2024 05:53:15 +0800 Subject: [PATCH] book: fix imprecise description of `NULL` in C++ (#279) --- book/en-us/02-usability.md | 17 +++++++++-------- book/zh-cn/02-usability.md | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/book/en-us/02-usability.md b/book/en-us/02-usability.md index 6da7d8e5..51d3edcf 100644 --- a/book/en-us/02-usability.md +++ b/book/en-us/02-usability.md @@ -18,20 +18,21 @@ which refers to the language behavior that occurred before the runtime. ### nullptr -The purpose of `nullptr` appears to replace `NULL`. In a sense, -traditional C++ treats `NULL` and `0` as the same thing, -depending on how the compiler defines NULL, -and some compilers define NULL as `((void*)0)` Some will define it directly as `0`. +The purpose of `nullptr` appears to replace `NULL`. There are **null pointer constants** in the C and C++ languages, +which can be implicitly converted to null pointer value of any pointer type, +or null member pointer value of any pointer-to-member type in C++. +`NULL` is provided by the standard library implementation and defined as an implementation-defined null pointer constant. +In C, some standard libraries defines `NULL` as `((void*)0)` and some define it as `0`. -C++ **does not allow** to implicitly convert `void *` to other types. -But if the compiler tries to define `NULL` as `((void*)0)`, then in the following code: +C++ **does not allow** to implicitly convert `void *` to other types, and thus `((void*)0)` is not a valid implementation +of `NULL`. If the standard library tries to define `NULL` as `((void*)0)`, then compilation error would occur in the following code: ```cpp char *ch = NULL; ``` C++ without the `void *` implicit conversion has to define `NULL` as `0`. -This still creates a new problem. Defining `NULL` to 0 will cause the overloading feature in `C++` to be confusing. +This still creates a new problem. Defining `NULL` to `0` will cause the overloading feature in `C++` to be confusing. Consider the following two `foo` functions: ```cpp @@ -41,7 +42,7 @@ void foo(int); Then the `foo(NULL);` statement will call `foo(int)`, which will cause the code to be counterintuitive. -To solve this problem, C++11 introduced the `nullptr` keyword, which is specifically used to distinguish null pointers, 0. The type of `nullptr` is `nullptr_t`, which can be implicitly converted to any pointer or member pointer type, and can be compared equally or unequally with them. +To solve this problem, C++11 introduced the `nullptr` keyword, which is specifically used to distinguish null pointers, `0`. The type of `nullptr` is `nullptr_t`, which can be implicitly converted to any pointer or member pointer type, and can be compared equally or unequally with them. You can try to compile the following code using clang++: diff --git a/book/zh-cn/02-usability.md b/book/zh-cn/02-usability.md index ed4fe982..11047e7e 100644 --- a/book/zh-cn/02-usability.md +++ b/book/zh-cn/02-usability.md @@ -14,9 +14,9 @@ order: 2 ### nullptr -`nullptr` 出现的目的是为了替代 `NULL`。在某种意义上来说,传统 C++ 会把 `NULL`、`0` 视为同一种东西,这取决于编译器如何定义 `NULL`,有些编译器会将 `NULL` 定义为 `((void*)0)`,有些则会直接将其定义为 `0`。 +`nullptr` 出现的目的是为了替代 `NULL`。 C 与 C++ 语言中有**空指针常量**,它们能被隐式转换成任何指针类型的空指针值,或 C++ 中的任何成员指针类型的空成员指针值。 `NULL` 由标准库实现提供,并被定义为实现定义的空指针常量。在 C 中,有些标准库会把 `NULL` 定义为 `((void*)0)` 而有些将它定义为 `0`。 -C++ **不允许**直接将 `void *` 隐式转换到其他类型。但如果编译器尝试把 `NULL` 定义为 `((void*)0)`,那么在下面这句代码中: +C++ **不允许**直接将 `void *` 隐式转换到其他类型,从而 `((void*)0)` 不是 `NULL` 的合法实现。如果标准库尝试把 `NULL` 定义为 `((void*)0)`,那么下面这句代码中会出现编译错误: ```cpp char *ch = NULL;