某些时候,我们需要将指针赋值为空指针,以防止野指针。

 
有人喜欢使用NULL作为空指针常量使用,例如:int* p = NULL;。
也有人直接使用0值作为空指针常量,例如:int* p = 0;。
 
前者可能觉得:NULL作为空指针常量,名字很形象,可读性较强。
后者可能觉得:NULL并不是C/C++语言的关键字,而是一个在标准库头文件<stddef.h>中定义的宏,因此要使用NULL,可能需要直接或简介地包含<stddef.h>头文件,比较麻烦。
 
问题一:NULL与常数0值有何区别?
 
要弄清楚这个问题,我们采用问与答的形式来描述。
 
问:NULL到底是什么?
 
答:NULL是一个宏。
 
问:它的值是多少?
 
答:C/C++标准规定:它的值是一个空指针常量(null pointer constant),由实现定义。#1,#2
 
问:什么样的值才能称之为空指针常量?
 
答:C语言中常数0和(void*)0都是空指针常量;C++中(暂且忽略C++11)常数0是,而(void*)0 不是。#3,#4
 
问:NULL宏是在哪里定义的?
 
答:通常是在C标准库的<stddef.h>头文件中,不过别的头文件中可能也有定义。
 
问:一般编译器的<stddef.h>头文件中NULL宏是如何定义的?
 
答:以gcc或clang编译器为例,NULL的定义大致如下(稍有简化):
#if defined(__cplusplus)
# define NULL // C++中使用0作为NULL的值
#else
# define NULL ((void *)) // C中使用((void *)0)作为NULL的值
#endif

问:为什么C中(void*)0是空指针常量,而C++中不是?

 
答:因为C语言中任何类型的指针都可以(隐式地)转换为void*型,反过来也行,而C++中void*型不能隐式地转换为别的类型指针(例如:int*p = (void*)0;使用C++编译器编译会报错)。#5,#6
 
问:既然C/C++标准中,常数0都可作为空指针常量,为什么不统一使用0?
 
答:个人觉得由于(void*)0更能体现指针的意义,而常数0更多的时候是用作整数。因此,C语言中NULL定义选择了(void*)0。(仅供参考)
 
问题二:C++11中为什么要引入nullptr?
 
考虑着这样一个函数重载的情形:
#include <stddef.h>
void foo(int) {} // #1
void foo(char*) {} // #2
int main() {
foo(NULL); // 调用#1还是#2?
}

从字面上来讲,NULL是个空指针常量,我们可能会觉得:既然是个指针,那么应该调用#2。但事实上调用的却是#1,因为C++中NULL扩展为常数0,它是int型。

 
根本原因就是:常数0既是整数常量,也是空指针常量。
 
为了解决这种二义性,C++11标准引入了关键字nullptr,它作为一种空指针常量。#7例如:
void foo(int) {}     // #1
void foo(char*) {} // #2
int main() {
foo(nullptr); // 它会毫无异议地调用#2
}

附注:

 
[#1] C99: 7.17-p3:
    The macros are
        NULL
    which expands to an implementation-defined null pointer constant; and ...
 
[#2] C++03: 18.1-p4:
    The macro NULL is an implementation-defined C + + null pointer constant in this International Standard(4.10).
 
[#3] C99: 6.3.2.3-p3:
    An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.
 
[#4] C++03: 4.10-p1:
    A null pointer constant is an integral constant expression (5.19) rvalue of integer type that evaluates to zero.
 
[#5] C99: 6.3.2.3-p1:
    A pointer to void may be converted to or from a pointer to any incomplete or object type. A pointer to any incomplete or object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.
 
[#6] C++03: 4.10-p2:
    An rvalue of type “pointer to cv T,” where T is an object type, can be converted to an rvalue of type “pointer to cv void.”
 
[#7] C++11: 4.10-p1:
    A null pointer constant is an integral constant expression (5.19) prvalue of integer type that evaluates to zero or a prvalue of type std::nullptr_t.

最新文章

  1. Httpd运维日志:通过apxs添加模块
  2. Android VersionedGestureDetector手势事件
  3. 运行Python2.x程序报编码错误的解决办法-UnicodeDecodeError: &#39;ascii&#39; codec can&#39;t decode byte 0xb7 in position 7: ordina not in range(128)
  4. java学习笔记_GUI(1)
  5. 【HDOJ】1501 Zipper
  6. iOS中__block 关键字的底层实现原理
  7. [转载]opencv +linux
  8. ASP.NET 开发框架汇总
  9. 框架基础JNI
  10. 已有 JS 模块化和打包方案收集
  11. HTML表单基本格式与代码
  12. 2017年4月 TIOBE 编程语言排名
  13. 蚂蚁金服新一代数据可视化引擎 G2
  14. 【经验随笔】MYSQL表加锁升级导致数据库访问失败
  15. 数据分析---《Python for Data Analysis》学习笔记【02】
  16. 简单谈谈$.merge()
  17. [HAOI2008]移动玩具
  18. Qt 4.8.2.+VS2008静态编译
  19. Java知多少(38)抽象类的概念和使用
  20. 在vi 按了Ctrl s 之后..

热门文章

  1. BZOJ3590 SNOI2013Quare(状压dp)
  2. 【BZOJ2427】[HAOI2010]软件安装(动态规划,Tarjan)
  3. FinalHttp的简要介绍与使用
  4. SDL源码阅读笔记(1) 基本模块
  5. Luogu 2668 NOIP 2015 斗地主(搜索,动态规划)
  6. 几个简单常用的Sql语句
  7. 洛谷P4413 R2
  8. 写入与读取第三方的 cookie - P3P: CP=&quot;CAO PSA OUR&quot;
  9. Druid数据源对数据库访问密码加密好麻烦
  10. hdu 3966(树链剖分+线段树区间更新)