c - NULL、 '\0' 和 0 有什么区别?

标签 c pointers null

在 C 语言中,各种零值之间似乎存在差异——NULLNUL0

我知道 ASCII 字符 '0' 的计算结果为 480x30

NULL 指针通常定义为:

#define NULL 0

或者

#define NULL (void *)0

此外,还有一个 NUL 字符 '\0',它的计算结果似乎也是 0

有时这三个值不能相等吗?

在 64 位系统上也是如此吗?

最佳答案

注意:此答案适用于 C 语言,不适用于 C++。


空指针

整型常量 0 具有不同的含义,具体取决于使用它的上下文。在所有情况下,它仍然是一个整数常量,值为0,只是描述方式不同而已。

如果将指针与常量文字 0 进行比较,则检查该指针是否为空指针。这个 0 然后被称为空指针常量。 C 标准定义将 0 转换为类型 void * 既是空指针又是空指针常量。

此外,为了提高可读性,头文件stddef.h 中提供了宏NULL。根据您的编译器,可能会 #undef NULL 并将其重新定义为古怪的东西。

因此,这里有一些检查空指针的有效方法:

if (pointer == NULL)

NULL 被定义为比较等于空指针。 NULL 的实际定义是由实现定义的,只要它是一个有效的空指针常量即可。

if (pointer == 0)

0 是空指针常量的另一种表示。

if (!pointer)

if 语句隐式检查“不为 0”,因此我们将其反转为“为 0”。

以下是检查空指针的无效方法:

int mynull = 0;
<some code>
if (pointer == mynull)

对于编译器来说,这不是对空指针的检查,而是对两个变量的相等性检查。这可能如果代码中的 mynull 永远不会改变并且编译器优化常量将 0 折叠到 if 语句中,这可能工作,但这不能保证并且编译器必须产生至少一个诊断消息(警告或错误) 根据 C 标准。

请注意,C 语言中空指针的值与底层架构无关。如果底层架构有一个定义为地址 0xDEADBEEF 的空指针值,则由编译器来解决这个问题。

因此,即使在这个有趣的架构上,以下方法仍然是检查空指针的有效方法:

if (!pointer)
if (pointer == NULL)
if (pointer == 0)

以下是检查空指针的无效方法:

#define MYNULL (void *) 0xDEADBEEF
if (pointer == MYNULL)
if (pointer == 0xDEADBEEF)

因为这些被编译器视为正常比较。

空字符

'\0' 被定义为空字符 - 即所有位都设置为零的字符。 '\0' 是(与所有字 rune 字一样)整数常量,在本例中值为零。所以 '\0' 完全等同于一个朴素的 0 整数常量 - 唯一的区别在于它传达给人类读者的意图 (“我将其用作空字符。”)。

'\0' 与指针无关。但是,您可能会看到类似于此代码的内容:

if (!*char_pointer)

检查 char 指针是否指向空字符。

if (*char_pointer)

检查 char 指针是否指向非空字符。

不要将它们与空指针混淆。仅仅因为位表示是相同的,并且这允许一些方便的交叉情况,所以它们实际上不是一回事。

引用资料

参见 Question 5.3 of the comp.lang.c FAQ更多。 参见 this pdf对于C标准。查看 6.3.2.3 指针部分,第 3 段。

关于c - NULL、 '\0' 和 0 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1296843/

相关文章:

c - 在 C 中释放指向 malloc 内存的指针的副本

c - 这个 C 迭代是如何工作的?

将数据从内核空间复制到用户空间

c - 表达式 a^=b^=a^=b 中是否有序列点,或者是否未定义?

C:反转字符串时的段错误

php - 通过ajax到php的多维数组通过json_decode变成null

c++ - 指针数组作为函数参数

c++ - std::make_shared 中的原始指针

django - 在 Django Rest Framework 中保存序列化程序时将 None 传递给外键

android - 首次运行时的PreferenceScreen默认设置