在C语言中,各种零值之间似乎存在差异——NULL、NUL和0。
我知道ASCII字符“0”的值为48或0x30。
NULL指针通常定义为:
#define NULL 0
Or
#define NULL (void *)0
此外,还有NUL字符“\0”,它的值似乎也是0。
是否存在这三个值不能相等的情况?
在64位系统上也是这样吗?
在C语言中,各种零值之间似乎存在差异——NULL、NUL和0。
我知道ASCII字符“0”的值为48或0x30。
NULL指针通常定义为:
#define NULL 0
Or
#define NULL (void *)0
此外,还有NUL字符“\0”,它的值似乎也是0。
是否存在这三个值不能相等的情况?
在64位系统上也是这样吗?
当前回答
注意:这个答案适用于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段的“指针”。
其他回答
在ASCII表中,值为0x00的字节是称为NUL或NULL的特殊字符。在C语言中,因为你不应该在源代码中嵌入控制字符,所以这是用C字符串表示的,带有一个转义0,即\0。
但是一个真NULL不是一个值。它是一个值的缺失。对于指针来说,这意味着指针没有可指向的对象。在数据库中,它意味着字段中没有值(这与字段为空白、0或填充空格不同)。
给定的系统或数据库文件格式用来表示NULL的实际值不一定是0x00。
NULL不能保证为0——它的确切值取决于体系结构。大多数主流架构将其定义为(void*)0。
'\0'将总是等于0,因为这是字节0在字符字面值中编码的方式。
我不记得C编译器是否被要求使用ASCII——如果不是,'0'可能并不总是等于48。无论如何,除非您在非常晦涩的系统上工作,否则您不太可能遇到使用像EBCDIC这样的替代字符集的系统。
各种类型的大小在64位系统上有所不同,但整数值是相同的。
一些评论者表示怀疑NULL等于0,但不是0。下面是一个示例程序,以及在这样一个系统上的预期输出:
#include <stdio.h>
int main () {
size_t ii;
int *ptr = NULL;
unsigned long *null_value = (unsigned long *)&ptr;
if (NULL == 0) {
printf ("NULL == 0\n"); }
printf ("NULL = 0x");
for (ii = 0; ii < sizeof (ptr); ii++) {
printf ("%02X", null_value[ii]); }
printf ("\n");
return 0;
}
该程序可以输出:
NULL == 0
NULL = 0x00000001
“NUL”不是0,而是指ASCII的NUL字符。至少,我看到它是这样使用的。空指针通常定义为0,但这取决于您正在运行的环境,以及您正在使用的操作系统或语言的规范。
在ANSI C中,空指针被指定为整数值0。所以任何不符合标准的世界都是不符合ANSI C的。
注意:这个答案适用于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段的“指针”。
一篇帮助我开始学习C语言的好文章(摘自Linden的Expert C Programming)
一个l为空,两个l为空
记住这个小押韵来回忆指针和ASCII零的正确术语:
The one "l" NUL ends an ASCII string,
The two "l" NULL points to no thing.
Apologies to Ogden Nash, but the three "l" nulll means check your spelling.
位模式为0的ASCII字符称为“NUL”。 特殊的指针值意味着指针不指向任何地方是“NULL”。 这两个词在意思上是不可互换的。