在C语言中,各种零值之间似乎存在差异——NULL、NUL和0。

我知道ASCII字符“0”的值为48或0x30。

NULL指针通常定义为:

#define NULL 0

Or

#define NULL (void *)0

此外,还有NUL字符“\0”,它的值似乎也是0。

是否存在这三个值不能相等的情况?

在64位系统上也是这样吗?


当前回答

(void*) 0是NULL, '\0'表示字符串的结束。

其他回答

如果NULL和0是等价的空指针常数,我应该使用哪个?在C常见问题解答列表中也解决了这个问题:

C programmers must understand that NULL and 0 are interchangeable in pointer contexts, and that an uncast 0 is perfectly acceptable. Any usage of NULL (as opposed to 0) should be considered a gentle reminder that a pointer is involved; programmers should not depend on it (either for their own understanding or the compiler's) for distinguishing pointer 0's from integer 0's. It is only in pointer contexts that NULL and 0 are equivalent. NULL should not be used when another kind of 0 is required, even though it might work, because doing so sends the wrong stylistic message. (Furthermore, ANSI allows the definition of NULL to be ((void *)0), which will not work at all in non-pointer contexts.) In particular, do not use NULL when the ASCII null character (NUL) is desired. Provide your own definition

#define NUL '\0'

如果你一定要的话。

这三者在不同的上下文中定义了0的含义。

指针上下文-使用NULL,表示指针的值为0,与它是32位还是64位无关(一种情况是4字节,另一种情况是8字节的零)。 string context -表示数字0的字符的十六进制值为0x30,而NUL字符的十六进制值为0x00(用于终止字符串)。

当你查看内存时,这三个总是不同的:

NULL - 0x00000000 or 0x00000000'00000000 (32 vs 64 bit)
NUL - 0x00 or 0x0000 (ascii vs 2byte unicode)
'0' - 0x20

我希望这能解释清楚。

(void*) 0是NULL, '\0'表示字符串的结束。

在ASCII表中,值为0x00的字节是称为NUL或NULL的特殊字符。在C语言中,因为你不应该在源代码中嵌入控制字符,所以这是用C字符串表示的,带有一个转义0,即\0。

但是一个真NULL不是一个值。它是一个值的缺失。对于指针来说,这意味着指针没有可指向的对象。在数据库中,它意味着字段中没有值(这与字段为空白、0或填充空格不同)。

给定的系统或数据库文件格式用来表示NULL的实际值不一定是0x00。

注意:这个答案适用于C语言,而不是c++。


空指针

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

如果将一个指针与常量字面值0进行比较,那么这将检查该指针是否为空指针。这个0被称为空指针常量。C标准定义了转换为void *类型的0既是一个空指针,也是一个空指针常量。

此外,为了提高可读性,在头文件stddef.h中提供了宏NULL。取决于你的编译器,它可能是#undef NULL,并重新定义它的一些古怪的东西。

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

if (pointer == NULL)

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

if (pointer == 0)

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

if (!pointer)

这个if语句隐式检查“is not 0”,因此我们将其反转为“is 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'是一个整数常量(像所有字符字面值一样),在本例中值为0。因此,'\0'完全等同于一个未修饰的0整数常量——唯一的区别是它向人类读者传达的意图(“我将此用作空字符。”)。

“\0”与指针无关。然而,你可能会看到类似于下面代码的东西:

if (!*char_pointer)

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

if (*char_pointer)

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

不要把它们和空指针搞混了。只是因为位表示是相同的,这允许一些方便的交叉情况,它们实际上不是同一件事。

参考文献

更多信息请参见comp.lang.c常见问题中的问题5.3。 有关C标准,请参阅此pdf。请参阅第6.3.2.3节第3段的“指针”。