NULL,'\ 0'和0之间的区别是什么?

在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转换为typesvoid *既是一个空指针也是一个空指针常量。

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

因此,下面是一些检查空指针的有效方法:

 if (pointer == NULL) 

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

 if (pointer == 0) 

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

 if (!pointer) 

这个if语句隐式地检查“不是0”,所以我们把它翻转为“0”。

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

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

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

注意什么是C语言中的空指针。 它在底层架构上并不重要。 如果底层架构有一个定义为地址0xDEADBEEF的空指针值,那么由编译器来sorting这个混乱。

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

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

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

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

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

空字符

'\0'被定义为一个空字符 – 这是一个所有位设置为零的字符。 这与指针无关。 但是,您可能会看到类似于此代码的内容:

 if (!*string_pointer) 

检查string指针是否指向空字符

 if (*string_pointer) 

检查string指针是否指向非空字符

不要让这些与空指针混淆。 只是因为比特表示是相同的,并且这允许一些方便的交叉情况,它们并不是相同的东西。

另外, '\0' (就像所有字符文字一样)是一个整数常量,在这个例子中是零值。 所以'\0'完全等价于一个未经修饰的0整数常量 – 唯一的区别是它传达给人类读者的意图 (“我将它作为空字符使用”)。

参考

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

看来很多人误解了NULL,'\ 0'和0之间的区别。 所以,要解释一下,并试图避免重复之前所说的话:

types为int的常量expression式的值为0,或者是此types的expression式,types转换为void *是一个空指针常量 ,如果转换为指针则变为空指针 。 标准保证比较不等于指向任何对象或函数的指针

NULL是一个macros,定义为一个空指针常量

'\ 0'是一个用于表示空字符的结构 ,用于终止一个string。

空字符是其所有位都设置为0的字节。

三者在不同的语境中定义零的含义。

  • 指针上下文 – 使用NULL,意味着指针的值是0,不pipe它是32位还是64位(一种情况下是4个字节,其他8个字节是0)。
  • string上下文 – 表示数字零的字符的hex值为0x30,而NUL字符的hex值为0x00(用于终止string)。

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

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

我希望这个澄清。

NULL,'\ 0'和0之间的区别是什么?

“空字符(NUL)”是最容易排除的。 '\0'是一个字符文字。 在C中,它被实现为int ,所以它和INT_TYPE_SIZE 0一样。 在C ++中,字符字面量被实现为char ,即1个字节。 这通常与NULL0不同。

接下来, NULL是一个指针值,指定一个variables不指向任何地址空间。 抛开通常实现为零的事实,它必须能够expression体系结构的完整地址空间。 因此,在32位体系结构中,NULL(可能)是4字节,而在64位体系结构中是8字节。 这取决于C的实施。

最后,文字0int型的,其大小为INT_TYPE_SIZEINT_TYPE_SIZE的默认值可能会因体系结构而有所不同。

苹果写道:

Mac OS X使用的64位数据模型被称为“LP64”。 这是来自Sun和SGI以及64位Linux的其他64位UNIX系统所使用的通用数据模型。 LP64数据模型定义如下基元types:

  • 整数是32位
  • 多头是64位
  • 多头也是64位
  • 指针是64位的

维基百科64位 :

微软的VC ++编译器使用LLP64模型。

 64-bit data models Data model short int long long long pointers Sample operating systems LLP64 16 32 32 64 64 Microsoft Win64 (X64/IA64) LP64 16 32 64 64 64 Most Unix and Unix-like systems (Solaris, Linux, etc.) ILP64 16 64 64 64 64 HAL SILP64 64 64 64 64 64 ? 

编辑 :添加更多的字符文字。

 #include <stdio.h> int main(void) { printf("%d", sizeof('\0')); return 0; } 

上面的代码在gcc上返回4,在g ++上返回1。

如果NULL和0等价于空指针常量,应该使用哪一个? 在C FAQ列表中也解决了这个问题:

C程序员必须明白NULL0在指针上下文中是可以互换的,而uncast 0是完全可以接受的。 任何使用NULL(而不是0 )应该被认为是一个温和的提醒,指针是涉及的; 程序员不应该依赖它(或者是为了自己的理解,或者是为了编译器)来区分指针0和整数0

只有在指针上下文中, NULL0是等价的。 当需要另一种types的0时,不应使用NULL ,即使它可能工作,因为这样做会发送错误的样式消息。 (此外,ANSI允许NULL的定义为((void *)0) ,在非指针上下文中根本不起作用。)特别是,当需要ASCII空字符( NUL )时,不要使用NULL 。 提供你自己的定义

 #define NUL '\0' 

如果你必须。

一个L的NUL,它结束一个string。

一个两L的NULL指向任何东西。

我会打赌一头金牛

那没有三L的NULLL。

你如何处理NUL?

一个好的作品,帮助我从C开始(来自Linden的C编程专家)

一个'n'nul和两个'l'null

记住这个小韵,回忆一下指针和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. 

位模式为零的ASCII字符被称为“NUL”。 指针指向无处的特殊指针值是“NULL”。 这两个术语在含义上是不可互换的。

“NUL”不是0,而是指ASCII NUL字符。 至less,这是我见过的。 空指针通常被定义为0,但这取决于你正在运行的环境,以及你正在使用的操作系统或语言的规范。

在ANSI C中,空指针被指定为整数值0.所以任何不是真的世界都不符合ANSI C标准。

在ASCII表中,值为0x00的字节是称为“NUL”或“NULL”的特殊字符。 在C中,由于不应该在源代码中embedded控制字符,所以在Cstring中用0表示,即“\ 0”。

但是真正的NULL 不是一个值。 这是没有价值。 对于指针来说,这意味着指针没有任何指向。 在数据库中,这意味着在一个字段中没有任何值(与字段为空,0或空格填充不同)。

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

NULL不能保证是0 – 它的确切值是依赖于体系结构的。 大多数主要体系结构将其定义为(void*)0

'\0'将始终等于0,因为这是如何在字符字面值中编码字节0。

我不记得C编译器是否需要使用ASCII,如果不是,那么'0'不一定等于48.不pipe怎样,你不可能遇到一个使用EBCDIC这样的替代字符集的系统,除非你在非常晦涩的系统上工作。

在64位系统中,各种types的大小将有所不同,但是整数值将是相同的。


一些评论者表示怀疑NULL等于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 

(void *)0是NULL,'\ 0'表示string的结尾。