NULL,'\ 0'和0之间有什么区别

gna*_*avi 287 c null pointers

在C中,似乎有零各个值之间的差- NULL,NUL0.

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

NULL指针通常定义为:

#define NULL 0
Run Code Online (Sandbox Code Playgroud)

要么

#define NULL (void *)0
Run Code Online (Sandbox Code Playgroud)

另外,也有似乎评价的NUL人物.'\0'0

是否有时候这三个值不相等?

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

And*_*ton 333

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


空指针

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

如果将指针与常量文字进行比较0,则检查指针是否为空指针.这0随后被称为一个空指针常数.C标准定义0对类型的强制转换void *既是空指针又是空指针常量.

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

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

if (pointer == NULL)
Run Code Online (Sandbox Code Playgroud)

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

if (pointer == 0)
Run Code Online (Sandbox Code Playgroud)

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

if (!pointer)
Run Code Online (Sandbox Code Playgroud)

if语句隐式检查"不是0",因此我们将其反转为"是0".

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

int mynull = 0;
<some code>
if (pointer == mynull)
Run Code Online (Sandbox Code Playgroud)

对于编译器,这不是检查空指针,而是检查两个变量.如果mynull永远不会在代码中发生变化并且编译器优化常量将0折叠到if语句中,这可能会有效,但这不能保证,并且编译器必须根据C标准生成至少一条诊断消息(警告或错误).

请注意,C语言中的空指针是什么.它与底层架构无关.如果底层架构的空指针值定义为地址0xDEADBEEF,那么由编译器来排除这个混乱局面.

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

if (!pointer)
if (pointer == NULL)
if (pointer == 0)
Run Code Online (Sandbox Code Playgroud)

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

#define MYNULL (void *) 0xDEADBEEF
if (pointer == MYNULL)
if (pointer == 0xDEADBEEF)
Run Code Online (Sandbox Code Playgroud)

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

空字符

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

if (!*string_pointer)
Run Code Online (Sandbox Code Playgroud)

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

if (*string_pointer)
Run Code Online (Sandbox Code Playgroud)

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

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

另外,'\0'(像所有字符文字一样)是一个整数常量,在这种情况下值为零.所以'\0'完全等同于一个朴实的0整数常量 - 唯一的区别在于它传达给人类读者的意图("我将它用作空字符.").

参考

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

  • 您将内置比较运算符作为比较位串的东西.但那不是它的本质.它比较了两个值,即抽象概念.所以内部表示为"0xDEADBEEF"的空指针仍然是一个空指针,无论它的位串是什么样的,它仍然会比较等于`NULL`,`0`,`\ 0`和所有其他空指针不断的形式. (6认同)
  • 不,你不会将`ptr`与*all-bits-zero*进行比较.这不是`memcmp`,但这是使用内置运算符的比较.一边是空指针常量''\ 0'`,另一边是指针.以及其他两个版本的"NULL"和"0".这三个人做同样的事情. (4认同)
  • 感谢您指向常见问题列表.但是,请参阅http://c-faq.com/null/nullor0.html (3认同)
  • 您对比较运算符提出了很好的观点。我刷了 C99。它说“一个值为 0 的整数常量表达式,或者这样一个转换为 void * 类型的表达式,称为空指针常量。” 它还说字符文字是整数常量表达式。因此,根据传递属性,`ptr == '\0'` 是对的。 (2认同)
  • "....有可能#undef NULL并将其重新定义为古怪的东西.任何这样做的人都应该被枪杀." 我的好先生让我大笑起来...... (2认同)

小智 33

似乎很多人误解了NULL,'\ 0'和0之间的区别.所以,要解释,并试图避免重复前面说过的事情:

类型为int的类型为0的常量表达式,或者此类型的表达式,强制转换为类型void*是一个空指针常量,如果转换为指针,则变为空指针.标准保证比较不等于任何指向任何对象或函数的指针.

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

'\ 0'是用于表示空字符的结构,用于终止字符串.

一个空字符是有它的所有位设置为0字节.

  • +1,即使是精确的'\ 0'是由值的八进制表示定义的字符.标准将'\ N','\ NN'和'\ NNN'定义为以八进制表示N,NN和NNN的字符文字. (7认同)
  • 你错过了“0”。 (2认同)

Nas*_*sko 13

所有三个都在不同的上下文中定义了零的含义.

  • 指针上下文 - 使用NULL并表示指针的值为0,与其是32位还是64位无关(一个4字节,另外8个字节为0).
  • 字符串上下文 - 表示数字零的字符的十六进制值为0x30,而NUL字符的十六进制值为0x00(用于终止字符串).

当你看到记忆时,这三个总是不同的:

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

我希望这能澄清它.

  • Nasko:评估`sizeof('\ 0')`并感到惊讶. (7认同)
  • @Nasko:我真的很惊讶:使用gcc,在C:sizeof('\ 0')== sizeof('a')== 4,而使用g ++,在C++中:sizeof('\ 0')== sizeof ('a')== 1 (2认同)

Sin*_*nür 6

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

C程序员必须理解它 NULL并且0在指针上下文中是可互换的,并且uncast 0 是完全可以接受的.任何使用NULL(相对于0)都应该被认为是一个温和的提示,指示涉及指针; 程序员不应该依赖它(无论是为了他们自己的理解还是编译器)来区分指针 0和整数0.

它只在指针上下文中 NULL并且0是等价的.NULL当需要另一种0时,即使它可能有效,也不应该使用它,因为这样做会发送错误的风格信息.(此外,ANSI允许的定义NULL((void *)0),不会在非指针上下文在所有的工作.)特别是,不使用NULL该ASCII空字符(时NUL)是期望的.提供您自己的定义

#define NUL '\0'
Run Code Online (Sandbox Code Playgroud)

如果你必须.


Eug*_*ota 5

NULL,'\ 0'和0之间有什么区别

"null character(NUL)"最容易排除. '\0'是一个字符文字.在C中,它实现为int,因此,它与0相同,即0 INT_TYPE_SIZE.在C++中,字符文字实现为char1字节.这通常与NULL或不同0.

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

最后,文字0是类型int,大小INT_TYPE_SIZE.默认值INT_TYPE_SIZE可能因架构而异.

Apple写道:

Mac OS X使用的64位数据模型称为"LP64".这是Sun和SGI以及64位Linux的其他64位UNIX系统使用的通用数据模型.LP64数据模型定义了基本类型,如下所示:

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

维基百科64位:

Microsoft的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       ?
Run Code Online (Sandbox Code Playgroud)

编辑:在字符文字上添加更多内容.

#include <stdio.h>

int main(void) {
    printf("%d", sizeof('\0'));
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

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

  • 不,''\ 0'`*不是*1字节值.它是一个字符文字,它是一个整数常量表达式 - 所以如果它可以说有一个大小那么它就是`int`的大小(必须至少为2个字节).如果你不相信我,请评估`sizeof('\ 0')`并亲自看看.`'\ 0'`,`0`和`0x0`都完全等价. (2认同)
  • 你应该在打印sizeof(东西)时使用"%zu" (2认同)

dlm*_*tei 5

一篇对我开始学习 C 很有帮助的好文章(摘自 Linden 的《专家 C 编程》)

一个“l”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. 
Run Code Online (Sandbox Code Playgroud)
  • 位模式为零的 ASCII 字符称为“NUL”。
  • 表示指针不指向任何地方的特殊指针值为“NULL”。
  • 这两个术语在含义上不可互换。