空指针和0、NULL之间的关系

本文详细解析了空指针、空指针常量及NULL的概念,并探讨了它们之间的关系,包括不同系统中的实现差异、如何判断空指针以及malloc函数在内存分配失败时的行为。

空指针和0NULL之间的关系

1.        什么是空指针常量(null pointer constant?

英文定义:

[6.3.2.3-3] An integer constant expression withthe value 0, or such an expression cast to type void *, is called a nullpointer constant.

即:具有0值的整型常量表达式或具有0值的并转换成void *类型的表达式都叫做空指针常量。

故,我们可以说0、0L、'/0'、3 - 3、0 * 17 (它们都是“integer constant expression”)以及 (void*)0等都是空指针常量。注意 (char*) 0不叫空指针常量,只是一个空指针值      至于系统选取哪种形式作为空指针常量使用,则与实现相关的。一般的 C系统选择 (void*)0 或者 0 的居多(也有个别的选择 0L);至于 C++ 系统,由于存在严格的类型转化的要求,void* 不能像C 中那样自由转换为其它指针类型,所以通常选 0 作为空指针常量(tyc: C++标准推荐),而不选择 (void*)0

2.        什么是空指针(null pointer?

英文定义:

[6.3.2.3-3] If a null pointer constant isconverted to a pointer type, the resulting pointer, called a null pointer, isguaranteed to compare unequal to a pointer to any object or function.

即:如果把一个空指针常量转换成指针,那么这个指针就被叫做空指针。

故,如果 p是一个指针变量,则 p = 0;p = 0L; p = '/0';p = 3 - 3; p = 0 * 17中的任何一种赋值操作之后(对于 C来说还可以是 p = (void*)0;), p都成为一个空指针,由系统保证空指针不指向任何实际的对象或者函数。反过来说,任何对象或者函数的地址都不可能是空指针。

例如:char *p; //定义一个字符指针p

             p=0; // p被初始化为空指针

3.     什么是 NULL
英文定义:
[6.3.2.3-Footnote]The macro NULL is defined in <stddef.h> (and other headers) as a nullpointer constant

即: NULL是一个标准规定的宏定义,用来表示空指针常量

故,除了上面的各种赋值方式之外,还可以用 p =NULL;来使 p成为一个空指针。(tyc:很多系统中的实现:#define NULL (void*)0,与这里的“a null pointer constant”并不是完全一致的)。

注意:使用NULL时必须包含相应的头文件。

4.     空指针(null pointer)指向了内存的什么地方(空指针的内部实现)?
标准并没有对空指针指向内存中的什么地方这一个问题作出规定,也就是说用哪个具体的地址值(0x0地址还是某一特定地址)表示空指针取决于系统的实现。我们常见的空指针一般指向 0 地址,即空指针的内部用全 0 来表示(zero null pointer,零空指针);也有一些系统用一些特殊的地址值或者特殊的方式表示空指针(nonzero null pointer,非零空指针),具体请参见C FAQ

幸运的是,在实际编程中不需要了解在我们的系统上空指针到底是一个 zero null pointer还是 nonzero null pointer我们只需要了解一个指针是否是空指针就可以了——编译器会自动实现其中的转换,为我们屏蔽其中的实现细节。注意:不要把空指针的内部表示等同于整数 0 的对象表示——如上所述,有时它们是不同的。

5.     如何判断一个指针是否是一个空指针?

这可以通过与空指针常量或者其它的空指针的比较来实现(注意与空指针的内部表示无关)。例如,假设 p是一个指针变量,q是一个同类型的空指针,要检查 p是否是一个空指针,可以采用下列任意形式之一——它们在实现的功能上都是等价的,所不同的只是风格的差别。

指针变量 p是空指针的判断:
if ( p == 0 )
if ( p == '/0' )

if ( p == 3 - 3 )

if ( p == NULL )  /* 使用 NULL 必须包含相应的标准库的头文件 */
if ( NULL == p )

if ( !p )
if ( p == q )
...

指针变量 p不是空指针的判断:
if ( p != 0 )

if ( p != '/0' )
if ( p != 3 - 3 )
if ( p != NULL)  /* 使用 NULL 必须包含相应的标准库的头文件 */
if ( NULL != p )

if ( p )
if ( p != q )
...

6.     可以用 memset函数来得到一个空指针吗?
这个问题等同于:如果 p是一个指针变量,那么
memset( &p, 0, sizeof(p) );
p = 0;
是等价的吗?
答案是否定的,虽然在大多数系统上是等价的,但是因为有的系统存在着非零空指针nonzero null pointer),所以这时两者不等价。由于这个原因,要注意当想将指针设置为空指针的时候不应该使用 memset,而应该用空指针常量或空指针对指针变量赋值或者初始化的方法。

7.     可以定义自己的 NULL的实现吗?兼答"NULL的值可以是 123等值吗?"类似问题
[7.1.3-2] If the program declares or defines an identifier in a context inwhich it is reserved (other than as allowed by 7.1.4), or defines a reservedidentifier as a macro name, the behavior is undefined.
NULL
是标准库中的一个符合上述条件的reserved identifier(保留标识符)。所以,如果包含了相应的标准头文件而引入了NULL的话,则再在程序中重新定义NULL为不同的内容是非法的,其行为是未定义的。也就是说,如果是符合标准的程序,其 NULL的值只能是 0,不可能是除 0之外的其它值,比如 123等。

测试:

#define NULL 1    //将NULL定义为1

char*p=NULL; //错误,VS2010编译器提示“int”类型的值不能用于初始化”char”类型实体;而如果把NULL定义为0,就可以

如果想自己定义NULL,它只能定义为0,可以如下定义:
#ifndef  NULL

#define NULL 0

#endif

8.     malloc 函数在分配内存失败时返回 0 还是 NULL
malloc
函数是标准 C规定的库函数。在标准中明确规定了在其内存分配失败时返回的是一个 “null pointer”(空指针):
[7.20.3-1] If the space cannot be allocated, a null pointer is returned.
对于空指针值,一般的文档(比如man)中倾向于用NULL表示,而没有直接说成 0。但是我们应该清楚:对于指针类型来说,返回 NULL返回 0是完全等价的,因为 NULL 0 都表示 “null pointer”(空指针)。(tyc:一般系统中手册中都返回NULL,那我们就用NULL

转自:http://wenku.baidu.com/view/250567c08bd63186bcebbcc0.html

 

 

<think> 首先,用户的问题是:"我想了解C++中空指针0的区别与联系 请问C++中空指针0的区别与联系"。我需要基于提供的引用系统指令来回答。 系统指令: - 所有行内数学表达式使用$...$格式。 - 独立公式使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如:[^1] - 回答结构清晰,帮助用户逐步解决问题,尽量保证回答真实可靠。 用户提供了几个引用: - [^1] 解释了CC++中NULL0的区别,提到00L等是空指针常量,C++通常选0作为空指针常量。 - [^2] 补充说赋值操作如p = 0;会使p成为空指针。 - [^3] 描述空指针的含义:不指向任何对象或函数。 - [^4] 提到使用NULL可能不是检测空指针的最佳方式。 核心主题是C++中空指针0的区别与联系。 关键点: - 在C++中,空指针是一个指针,不指向任何有效对象或函数。 - 数字0(包括其他整数常量表达式如0L、'\0'等)在赋值给指针时,会使指针成为空指针。 - C++推荐使用0作为空指针常量,而不是(void*)0,因为C++有严格的类型转换。 - 从C++11开始,引入了nullptr关键字,专门表示空指针,避免歧义。 联系: - 0可以用作空指针常量,赋值给指针变量会使它成为空指针。 - 空指针的值就是0,但表示不指向任何东西。 区别: - 0是一个整数值,而空指针是一个指针值。 - 使用0可能导致类型混淆,尤其是在函数重载时;nullptr更安全。 - 在C++中,NULL通常定义为00L,但nullptr是更好的选择。 我的回答应该: 1. 结构清晰:逐步解释区别联系。 2. 使用中文。 3. 在行内数学表达式中使用$...$,如指针变量p。 4. 生成相关问题。 5. 引用时添加引用标识。 大纲回答: - 介绍空指针的概念。 - 解释0如何用作空指针常量。 - 讨论区别:类型、安全性。 - 提到nullptr现代C++实践。 - 总结联系区别。 - 生成相关问题。 引用使用: - 在回答中,自然地引用来源。例如,当解释0作为空指针常量时,引用[^1]或[^2]。 - 引用标识加在段落末尾。 最终回答结构: 1. 简要概述。 2. 详细解释区别联系。 3. 生成相关问题。 4. 添加引用标识。 </think> ### C++中空指针0的区别与联系 在C++中,空指针数字0之间关系既有紧密联系,也存在关键区别。我将逐步解释这些概念,确保回答清晰可靠。空指针表示一个指针变量不指向任何有效对象或函数地址[^3],而0是一个整数值,但在特定上下文中可以用于表示空指针。以下是详细分析: #### 1. **联系:0作为空指针常量** - 在C++中,数字0(包括其他整数常量表达式如$0L$、$'\0'$、$3-3$等)可以被用作"空指针常量"。当您将0赋值给指针变量时,编译器会自动将其解释为一个空指针[^1][^2]。 - 例如: ```cpp int *p = 0; // p成为一个空指针 ``` - 这里,$p = 0;$ 等同于 $p = \text{nullptr};$(在C++11及以上),因为0被隐式转换为空指针值。系统保证空指针不指向任何有效地址[^3]。 - 联系的核心在于:**0是C++中推荐的空指针常量**。C++标准选择0(而非C语言中的$(void*)$0),因为C++有严格的类型系统,void*不能自由转换为其他指针类型[^1]。这使得0在赋值或比较操作中,能安全地表示空指针状态。 #### 2. **区别:类型、安全性语义** - **类型差异**: - 0是一个整数(int类型),而空指针是一个指针类型(如$int*$)。在赋值时,0隐式转换为指针类型,但这可能导致歧义。 - 示例:在函数重载场景中: ```cpp void func(int); // 重载1:接受整数 void func(int*); // 重载2:接受指针 func(0); // 调用func(int),因为0是int类型,而非指针 ``` 这里,$func(0)$不会调用指针版本,因为0被视为整数,而非空指针[^4]。使用$nullptr$(C++11引入)可避免此问题。 - 空指针的语义是"未分配或无效地址",而0仅是一个数值。编译器保证空指针与任何有效地址不相等,但0本身没有这种保证[^3]。 - **安全性问题**: - 使用0作为空指针可能引发类型错误。例如: ```cpp int *p = 0; // 安全:p是空指针 if (p == 0) { ... } // 安全,但依赖隐式转换 ``` 但如果使用宏或变量(如$#define NULL 0$),编译器可能无法优化或检测类型不匹配[^4]。 - 相比之下,C++11的$nullptr$是类型安全的空指针字面量: ```cpp int *p = nullptr; // 明确表示空指针 if (p == nullptr) { ... } // 无歧义 ``` $nullptr$避免了0的整数语义,减少错误。 - **NULL宏的陷阱**: - 在C++中,NULL通常定义为00L(例如$#define NULL 0$),但这本质上是整数。与0类似,NULL在类型推导中可能导致问题,而$nullptr$是更好的替代[^1][^4]。 #### 3. **总结区别与联系** - **联系**:0是C++中有效的空指针常量,赋值后能使指针成为空指针空指针的值在底层通常是0,表示"无地址"状态[^2][^3]。 - **区别**: | 方面 | 0 | 空指针(如$nullptr$) | |--------------|----------------------------------------|--------------------------------------| | **类型** | 整数(int) | 指针类型(如$int*$) | | **语义** | 数值零 | 表示无效地址 | | **安全性** | 可能引起类型混淆(如重载) | 类型安全,减少错误 | | **现代实践** | 遗留代码中使用,但不推荐 | C++11+推荐使用$nullptr$ | - 建议:在现代C++中,优先使用$nullptr$代替0NULL,以提高代码清晰度安全性。 #### 4. **最佳实践** - 在C++11及以上,始终使用$nullptr$表示空指针: ```cpp int *ptr = nullptr; // 正确:类型安全 if (ptr == nullptr) { ... } // 明确比较 ``` - 避免使用0NULL,除非维护旧代码。这能防止类型相关的bug[^1][^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值