比较中NULL和零之间的差异

Difference Between NULL and Zero in Comparing

本文关键字:之间 NULL 比较      更新时间:2023-10-16

我对NULL略知一二,但当涉及到比较时,我会感到困惑
例如:

int* p;
if(p == NULL){
//do stuff
}
if(p == 0){
//do stuff
}

在第一次比较中;p〃;与什么地址相比?

它是在寻找";p〃;,看看它是否有效?

在C的每个现代实现中,NULL为零,通常作为指针值:

#define  NULL  (void *) 0

因此,将字符与NULL进行比较可能是无效的:

char ch = 'a';
if (ch == NULL)     //  probably "invalid comparison of pointer with scalar"

作为一个指针值,选择NULL来指向无效内存,因此(在合适的体系结构上)取消引用它将导致内存故障。大多数虚拟机仅为此目的保留较低的内存,并通过保留未映射到物理内存的低内存来实现。有多少内存是没有保留的?可能是几千字节,但许多实现都保留了几兆字节。

NULL表示任何有效指针都未使用的值。因此,如果指针为NULL,那么它根本不指向任何变量。在指针上下文中,值零的含义与NULL相同,但是使用NULL而不是零更清楚。这就是关于NULL所需要了解的全部内容。

来自C99标准:

7.17常见定义<stddef.h>

3宏是

NULL

其扩展为实现定义的空指针常量。。。

来自C++11标准:

18.2类型

3宏NULL是本国际标准(4.10)中定义的C++空指针常量的实现

脚注194:

194)可能的定义包括00L,但不包括(void*)0

Microsoft VS 2008将其定义为:

/* Define NULL pointer value */
#ifndef NULL
#ifdef __cplusplus
#define NULL    0
#else
#define NULL    ((void *)0)
#endif
#endif

gcc/g++4.9.3将其定义为:

#if defined (_STDDEF_H) || defined (__need_NULL)
#undef NULL     /* in case <stdio.h> has defined it. */
#ifdef __GNUG__
#define NULL __null
#else   /* G++ */
#ifndef __cplusplus
#define NULL ((void *)0)
#else   /* C++ */
#define NULL 0
#endif  /* C++ */
#endif  /* G++ */
#endif  /* NULL not defined and <stddef.h> or need NULL.  */

我怀疑其他现代编译器也有类似的定义。

给定NULL的上述定义

if(p == NULL){

扩展到:

if(p == ((void*)0) ){

C.

它扩展到

if(p == 0){

在C++中。

在其他C++编译器中,这一行可以扩展到

if(p == 0L){

当使用C++11时,最好避免使用NULL,而开始使用nullptr

if ( p == nullptr ) {

从概念上讲,NULL是一个不指向任何地方的奇异指针值,并且可以隐式转换为任何指针类型
实际上,不幸的是,除非您在纯指针上下文中使用它,否则您不能依赖它作为指针值。

因此,在C++11和更高版本中使用nullptr,分别将0强制转换为右指针类型,尤其是在整数零不会转换为指针的情况下。

BTW:虽然在大多数现代系统中,空指针实际上都是零位,但这不是标准所要求的(可能有很多表示空指针的位模式,没有一个是全零的),并且对空指针常量在源代码中的表示方式没有任何区别。


在C++中:

NULL是本国际标准(4.10)中定义的C++空指针常量的实现

其定义为:

空指针常量是值为零的整数文字(2.14.2)或类型为std::nullptr_t的prvalue。

在C++11之前,最后一个选项显然不可用
在C++11之后,因为你不知道它是什么,所以你应该直接使用nullptr


在C:

宏是NULL其扩展为实现定义的空指针常量。。。

其定义为:

值为0的整数常量表达式或转换为void *类型的表达式称为空指针常量。

C++编译器中的NULL只是一个定义"空指针常量"(通常值为0)的宏。因此,除了NULL用于表示意图(这很重要)之外,没有什么区别。例如,您可以创建一个值为NULLint变量,该变量与标准声明(int a = 0;)相比没有任何特殊处理。

NULL不是"内存中的空白"。它只是一个符号,(通常)代表某种东西(值、指针等)的缺失

然而,现在不鼓励在C++中使用NULL,而应该使用更高级的nullptr

知道NULL是内存中的空白

不完全如此——NULL是一个定义良好的"无位置",与任何有效的内存地址都不对应。

在C和C++中,NULL宏都被定义为空指针常量,这是一个零值整数表达式。C++还提供了nullptr文本,该文本的计算结果也是空指针常量。当空指针常量出现在指针上下文中时,它将被转换为实现定义的空指针。空指针值可以是0值,也可以不是0值,但它保证与任何有效指针值进行不相等的比较。

C 2011在线标准:

6.3.2.3指针

3 nbsp nbsp;值为0的整数常量表达式,或转换为类型的此类表达式void*,称为空指针常量66)如果空指针常量被转换为指针类型,得到的指针,称为空指针,保证比较不相等指向指向任何对象或函数的指针。
66))宏CCD_ 26在CCD_;参见7.19

C++2014在线草案

2.13.7指针文本[lex.nullptr]
 nbsp nbsp指针文字
 nbsp nbsp nbsp nbsp;nullptr

1 nbsp nbsp;指针文字是关键字nullptr。它是一个类型为std::nullptr_t的prvalue。[:std::nullptr_t是既不是指针类型也不是指向成员类型的指针的不同类型;相反,这种类型的prvalue是空指针常量,并且可以转换为空指针值或空成员指针值。见4.10和4.11.-尾注]

4.10指针转换[conv.ptr]
1 nbsp nbsp;空指针常量是值为零的整数文字(2.13.2)或类型为std::nullptr_t的prvalue。空指针常量可以转换为指针类型;结果是该类型的空指针值并且可与对象指针或函数指针类型的每一个其它值区分开。这样的转换称为空指针转换。相同类型的两个空指针值应比较相等。这个将空指针常量转换为指向cv限定类型的指针是一次转换,而不是指针转换后的限定转换序列(4.4)积分类型可以被转换为类型为CCD_ 33的prvalue。[注意:生成的prvalue不是空指针值。--尾注]

18.2类型[support.Types]

3 nbsp nbsp;宏NULL是本国际标准中实现定义的C++空指针常量(4.10).194
194)可能的定义包括0和0L,但不包括(void*)0

把一些要点锤回家:

  1. NULL宏、nullptr文字(仅限C++)和空指针常量始终为0值
  2. 空指针不必为0值
  3. 空指针永远不会等于有效的内存地址
  4. 编译器的工作是将源代码中的空指针常量映射到生成的机器代码中的等效空指针;作为程序员,您(通常)不需要担心实现中的实际空指针
  5. 由于空指针常量总是0值,因此将指针值与0进行比较应等效于将其与NULLnullptr进行比较