C的NULL

在C语言中,我们使用NULL表示空指针,也就是我们可以写如下代码:

int *i = NULL;
foo_t *f = NULL;

实际上在C语言中,NULL通常被定义为如下:

#define NULL ((void *)0)

也就是说NULL实际上是一个void
*的指针,然后吧void *指针赋值给int *和foo_t
*的指针的时候,隐式转换成相应的类型。而如果换做一个C++编译器来编译的话是要出错的,因为C++是强类型的,void
*是不能隐式转换成其他指针类型的,所以通常情况下,编译器提供的头文件会这样定义NULL:

#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif

C++的0

因为C++中不能将void

*类型的指针隐式转换成其他指针类型,而又为了解决空指针的问题,所以C++中引入0来表示空指针,这样就有了类似上面的代码来定义NULL。实际上C++的书都会推荐说C++中更习惯使用0来表示空指针而不是NULL,尽管NULL在C++编译器下就是0。为什么C++的书都推荐使用0而不是NULL来表示空指针呢?我们看一个例子:

在foo.h文件中声明了一个函数:

void bar(sometype1 a, sometype2 *b);

这个函数在a.cpp、b.cpp中调用了,分别是:

a.cpp:


bar(a, b);

b.cpp:


bar(a, 0);

好的,这些代码都是正常完美的编译运行。但是突然在某个时候我们功能扩展,需要对bar函数进行扩展,我们使用了重载,现在foo.h的声明如下:

void bar(sometype1 a, sometype2 *b);
void bar(sometype1 a, int i);

这个时候危险了,a.cpp和b.cpp中的调用代码这个时候就不能按照期望的运行了。但是我们很快就会发现b.cpp中的0是整数,也就是在overload
resolution的时候,我们知道它调用的是void bar(sometype1 a, int
i)这个重载函数,于是我们可以做出如下修改让代码按照期望运行:

bar(a, static_cast<sometype2 *>(0));

我知道,如果我们一开始就有bar的这两个重载函数的话,我们会在一开始就想办法避免这个问题(不使用重载)或者我们写出正确的调用代码,然而后面的这个重载函数或许是我们几个月或者很长一段时间后加上的话,那我们出错的可能性就会加大了不少。貌似我们现在说道的这些跟C++通常使用0来表示空指针没什么关系,好吧,假设我们的调用代码是这样的:

foo.h

void bar(sometype1 a, sometype2 *b);

a.cpp


bar(a, b);

b.cpp


bar(a, NULL);

当bar的重载函数在后面加上来了之后,我们会发现出错了,但是出错的时候,我们找到b.cpp中的调用代码也很快可能忽略过去了,因为我们用的是NULL空指针啊,应该是调用的void
bar(sometype1 a, sometype2
*b)这个重载函数啊。实际上NULL在C++中就是0,写NULL这个反而会让你没那么警觉,因为NULL不够“明显”,而这里如果是使用0来表示空指针,那就会够“明显”,因为0是空指针,它更是一个整形常量。

在C++中,使用0来做为空指针会比使用NULL来做空指针会让你更加警觉。

C++ 11的nullptr

虽然上面我们说明了0比NULL可以让我们更加警觉,但是我们并没有避免这个问题。这个时候C++ 11的nullptr就很好的解决了这个问题,我们在C++ 11中使用nullptr来表示空指针,这样最早的代码是这样的,

foo.h

void bar(sometype1 a, sometype2 *b);

a.cpp


bar(a, b);

b.cpp


bar(a, nullptr);

在我们后来把bar的重载加上了之后,代码是这样:

foo.h

void bar(sometype1 a, sometype2 *b);
void bar(sometype1 a, int i);

a.cpp


bar(a, b);

b.cpp


bar(a, nullptr);

这时候,我们的代码还是能够如预期的一样正确运行。

在没有C++ 11的nullptr的时候,我们怎么解决避免这个问题呢?我们可以自己实现一个(《Imperfect C++》上面有一个实现):

const class nullptr_t
{
public:
    template<class T>
    inline operator T*() const
        { return 0; }

template<class C, class T>
    inline operator T C::*() const
        { return 0; }
 
private:
    void operator&() const;
} nullptr = {};

虽然这个东西被大家讨论过很多次了,但是我觉得还是有必要再讨论一下,毕竟在C++ 11还没有普及之前,我们还是应该知道怎么去避免问题,怎么很快的找到问题。

from:http://www.cppblog.com/airtrack/archive/2012/09/16/190828.aspx

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

  1. Javascript 中的false、0、null、undefined和空字符串对象

    在Javascript中,我们经常会接触到题目中提到的这5个比较特别的对象——false.0.空字符串.null和undefined.这几个对象很容易用错,因此在使用时必须得小心. 类型检测 我们下来 ...

  2. php中NULL、false、0、" "有何区别?

    php中很多还不懂php中0,"",null和false之间的区别,这些区别有时会影响到数据判断的正确性和安全性,给程序的测试运行造成很多麻烦.先看一个例子: <? $str ...

  3. empty和is_null以及isset函数在0、”0”、‘空串’、NULL、false、array()的计算值

    1empty:只要是非空或者非零的值都返回false,换句话说‘’.‘0’.0.null.false都返回true: 2is_null: 当参数满足下面三种情况时,is_null()将返回TRUE,其 ...

  4. c++11 NULL、0、nullptr

      C的NULL 在C语言中,我们使用NULL表示空指针,也就是我们可以写如下代码: int *i = NULL;foo_t *f = NULL; 实际上在C语言中,NULL通常被定义为如下: #de ...

  5. 史上最明白的 NULL、0、nullptr 区别分析(老师讲N篇都没讲明白的东东),今天终于明白了,如果和我一样以前不明白的可以好好的看看...

    C的NULL 在C语言中,我们使用NULL表示空指针,也就是我们可以写如下代码: int *i = NULL; foo_t *f = NULL; 实际上在C语言中,NULL通常被定义为如下: #def ...

  6. Javascript中那些你不知道的事之-- false、0、null、undefined和空字符串

    话不多说直接进入主题:(如果有写的不对的地方欢迎指正) 我们先来看看他们的类型分别是什么: typeof类型检测结果 结论:false是布尔类型对象,0是数字类型对象,null是object对象,un ...

  7. oracle基础:怎样把查询的null转换为0、打印、定义变量

    https://blog.csdn.net/xuxile/article/details/49943665 oracle怎样把查询的null转换为0 1.查询的null转换为0 NVL(Expr1,E ...

  8. NULL、0、nullptr的区别

    某些时候,我们需要将指针赋值为空指针,以防止野指针.   有人喜欢使用NULL作为空指针常量使用,例如:int* p = NULL;. 也有人直接使用0值作为空指针常量,例如:int* p = 0;. ...

  9. NULL、NUL、‘\0’、0以及EOF

    0 is an integer constant, '\0' is a character constant, nul is the name of the character constant. N ...

随机推荐

  1. 论文笔记 — MatchNet: Unifying Feature and Metric Learning for Patch-Based Matching

    论文:https://github.com/ei1994/my_reference_library/tree/master/papers 本文的贡献点如下: 1. 提出了一个新的利用深度网络架构基于p ...

  2. 解决:python命令行运行出错 ImportError: No module named ...

    一. 发现问题 今天在cmd命令行运行一个py文件,本来在pycharm中运行好好的文件,在命令行却报错了,直接提示我:ImportError: No module named 'homeworks' ...

  3. 《Advanced Bash-scripting Guide》学习(十二):占位符":"及其他

    本文所选的例子来自于<Advanced Bash-scripting Gudie>一书,译者 杨春敏 黄毅 : 在一个二元命令中提供一个占位符 例1. : ${username=`whoa ...

  4. count(*) 和count(1) 有区别吗

    create table test1 (a varchar2(2),b varchar2(2)); insert into test1 values ('b','c'); insert into te ...

  5. nyoj-1011-So Easy[II] (多边形面积求解)

    题目链接 /* Name:nyoj-1011-So Easy[II] Copyright: Author: Date: 2018/4/26 17:12:09 Description: 将多边形,从第一 ...

  6. translation exercise 3

    The high-resolution photograph was taken with a 135-mm lens mounted on a digital SLR camera.这张高清照片是用 ...

  7. MPEG4、XVID、AVC有什么区别

    MPEG-4包含XviD和DivX,而AVC优于二者mpeg4 DVD用的多,101mpeg4有AVC格式(加强版MP4)AVC/H.264是一种最新且技术含量最高的视频编码格式,由MPEG-4标准进 ...

  8. c# Http请求之HttpClient

    利用HttpClient进行Http请求,基于此,简单地封装了下: using System; using System.Collections.Generic; using System.Colle ...

  9. 忘记Oracle System和Sys密码的解决方法

    忘记Oracle System和Sys密码的方法 :Oracle提供两种验证方式,一种是OS验证,另一种密码文件验证方式,如果是第一种方式用以下方法修改密码: sqlplus /nolog; conn ...

  10. 解决 No module named PyQt5.QtWebKitWidgets

    原因:在 PyQt 5.6(+) 版本中, 新增 QtWebEngineWidgets 代替QtWebKitWidgets. 示例代码:#coding: utf-8 import sysfrom Py ...