在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位系统上也是这样吗?
当前回答
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
其他回答
一个1 - l的NUL,它结束一个字符串。
一个2l的NULL不指向任何东西。
我要赌一只金牛
没有3l null。
你如何处理NUL?
在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段的“指针”。
似乎很多人误解了NULL、'\0'和0之间的区别。为了避免重复之前说过的话,我来解释一下:
int类型的值为0的常量表达式,或该类型的表达式,转换为void *类型是空指针常量,如果转换为指针则成为空指针。该标准保证与指向任何对象或函数的任何指针的比较不相等。
NULL是一个宏,定义为空指针常量。
\0是一个用于表示空字符的结构,用于结束字符串。
空字符是一个所有位都设置为0的字节。
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