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

 
有人喜欢使用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.

NULL、0、nullptr的区别的更多相关文章

  1. C++ NULL与nullptr的区别

    C与C++中空指针的区别 在C里面,由于处处都要使用指针,所以导致NULL遍布各地.我们先来看C99是怎么定义NULL的: NULL can be defined as any null pointe ...

  2. (转)null和NULL和nullptr和””区别

    突然想到这个有趣的问题:C语言和C++对大小写是敏感的,也就是说null和NULL是区别对待的.NULL代表空地址,null只是一个符号.便来深究,看了很多资料,总结如下: 其实null和NULL都是 ...

  3. 聊一聊c++中指针为空的三种写法 ----->NULL, 0, nullptr

    看到同事用了一下nullptr.不是很了解这方面东东,找个帖子学习学习 http://www.cppblog.com/airtrack/archive/2012/09/16/190828.aspx N ...

  4. NULL和nullptr的区别

    //error C2665: “go”: 2 个重载中没有一个可以转换所有参数类型 #include <iostream> void go(int num) { std::cout < ...

  5. 再谈NULL和nullptr(C++11)区别

    在谈NULL和nullptr区别之前,我们先看段代码: #include "stdafx.h" #include <iostream> using namespace ...

  6. 字符串怎么换行 || 字符串中使用单引号时应该怎么写 || 保留两位小数 || 数字0在if中的意思是false || 什么情况下会会报undefined || null和undefined的区别 ||

    换行的字符串 "This string\nhas two lines" 字符串中使用单引号时应该怎么写 'You\'re right, it can\'t be a quote' ...

  7. C++中 0 与 NULL 与 nullptr之间的关系,nullptr_t 的实现

    C++中 0 与 NULL 与 nullptr之间的关系,nullptr_t 的实现 来源 http://blog.csdn.net/Virtual_Func/article/details/4975 ...

  8. NULL, '\0',0 '0'的区别

    如题,在程序中经常遇到NULL,和'\0',常常疑惑它们是什么关系,其实它们的值是一样的,只不过表现的形式不一样: 1.NULL; NULL 即空指针,在C和C++中的形式不一样,msdn上有如下的内 ...

  9. nil、Nil、NULL与NSNull的区别--备用

    我们来分别介绍一下这四种类型: 一.nil 我们给对象赋值时一般会使用object = nil,表示我想把这个对象释放掉: 或者对象由于某种原因,经过多次release,于是对象引用计数器为0了,系统 ...

  10. nil、Nil、NULL、NSNull的区别

    nil:指向一个对象的空指针,对objective c id 对象赋空值. Nil:指向一个类的空指针,表示对类进行赋空值. NULL:指向其他类型(如:基本类型.C类型)的空指针, 用于对非对象指针 ...

随机推荐

  1. appium学习记录 elements默认获取第一个元素

    封装 初始配置时候 要当做参数传入 element 发送的是一个元组 2  下标定位 当用elements进行定位时候 同时又有很多元素时候 默认获取第一个,但我们的元素是在后面时候 例如第四个 el ...

  2. BZOJ3963 WF2011MachineWorks(动态规划+斜率优化+cdq分治)

    按卖出时间排序后,设f[i]为买下第i台机器后的当前最大收益,则显然有f[i]=max{f[j]+gj*(di-dj-1)+rj-pi},且若此值<0,应设为-inf以表示无法购买第i台机器. ...

  3. SpringBoot基础入门

    1.SpringBoot核心相关内容 1.1入口类 SpringBoot通常有一个入口类*Application,内部有一个main方法,是启动SpringBoot的入口.使用@SpringBootA ...

  4. day30 __hash__ 计算哈希值

    hash() # __hash__哈希的时候会根据内存地址进行哈希,因为地址不同所以哈希的值也不同,哪怕是完全一样子的属性得出的哈希值也不一样因此存在需要某些时刻期望属性相同得出相同哈希值可以控制对象 ...

  5. Dependency Walker使用说明[转]

    在Windows世界中,有无数块活动的大陆,它们都有一个共同的名字——动态链接库.现在就让我们走进这些神奇的活动大陆,找出它们隐藏已久的秘密吧! 初窥门径:Windows的基石 随便打开一个系统目录, ...

  6. Hdoj 1008.Elevator 题解

    Problem Description The highest building in our city has only one elevator. A request list is made u ...

  7. 【洛谷5月月赛】玩游戏(NTT,生成函数)

    [洛谷5月月赛]玩游戏(NTT,生成函数) 题面 Luogu 题解 看一下要求的是什么东西 \((a_x+b_y)^i\)的期望.期望显然是所有答案和的平均数. 所以求出所有的答案就在乘一个逆元就好了 ...

  8. 【BZOJ3202】项链(莫比乌斯反演,Burnside引理)

    [BZOJ3202]项链(莫比乌斯反演,Burnside引理) 题面 BZOJ 洛谷 题解 首先读完题目,很明显的感觉就是,分成了两个部分计算. 首先计算本质不同的珠子个数,再计算本质不同的项链个数. ...

  9. 【BZOJ2000】[HNOI2000]取石头游戏(贪心,博弈论)

    [BZOJ2000][HNOI2000]取石头游戏(贪心,博弈论) 题面 BZOJ 洛谷 题解 这题好神仙啊,窝不会QaQ. 假装一下只有三个元素\(a_{i-1},a_i,a_{i+1}\),并且满 ...

  10. 【原创】py3+requests+json+xlwt,爬取拉勾招聘信息

    在拉勾搜索职位时,通过谷歌F12抓取请求信息 发现请求是一个post请求,参数为: 返回的是json数据 有了上面的基础,我们就可以构造请求了 然后对获取到的响应反序列化,这样就获取到了json格式的 ...