null,NULL,nullptr和””区别

本文介绍了C和C++中null、NULL、0以及空字符串的区别。NULL通常被定义为0,但在C++中使用0作为空指针更安全。C++11引入了nullptr,解决了类型安全问题。空字符串则是一个分配了空间的字符串对象,不同于未分配空间的null。

null,NULL,nullptr和””区别

C和C++对大小写敏感,null和NULL是区别对待的。
NULL代表空地址,null只是一个符号。
null和NULL都是字符串,具体看它们宏定义被定义成为什么值。在VS中NULL被定义为0,因为习惯上把宏定义的所有字符都大写,当把NULL它赋值给指针时意思为空,当然也可以把null定义为0。当它们都没定义时就只能叫符号,定义后就有另外的意思,直接把0赋值给指针也行,只要指针指向0就表示空。
NULL在有些编译器中已经赋值为0,不能再用#define定义它,会导致重定义问题。

C的NULL与C++的NULL

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

int *i = NULL;

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

#ifdef __cplusplus //简称:cpp c++ 文件
#define NULL 0
#else
#define NULL ((void *)0)
#endif

在C++环境下情况不能写这样的代码:

FILE* fp = (void*)0; //将void*直接赋值给一个指针是不合法的,编译器会报错

只能这样写代码

FILE* fp = (FILE*)0;
// or  
FILE* fp = 0;

C++的0

因为C++中不能将void *类型的指针隐式转换成其他指针类型,而又为了解决空指针的问题,所以C++中引入0来表示空指针(注:用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)); 

假设调用代码是这样的:

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

a.cpp
bar(a, b);

b.cpp
bar(a, NULL);

出错时b.cpp中调用代码的问题可能被忽略,因为使用NULL空指针容易直接认为调用的void bar(sometype1 a, sometype2 *b)这个重载函数。实际上NULL在C++中就是0,编程使用NULL时错误不够“明显”,使用0表示空指针更“明显”,因为0是空指针,它更是一个整型常量。所以在C++中,使用0来做空指针会比使用NULL来做空指针更加让人警觉。

C++ 11的nullptr

C++11中有一个新的关键字nullptr,如果编译器支持nullptr应该直接使用nullptr来替代NULL的宏定义。正常使用过程中它们是完全等价的。
虽然上面说明了0比NULL可以让我们更加警觉,但是并没有避免这个问题。C++ 11的nullptr能够解决这个问题,代码如下:

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,可以模拟实现一个nullptr

[cpp]
const  
class nullptr_t_t  
{  
public:  
    template<class T>          operator T*() const {return 0;}  
    template<class C, classT>  operator T C::*() const { return 0; }  
private:  
    void operator& () const; 
} nullptr_t = {};  
#undef NULL  
#define NULL nullptr_t  

C和C++的“”

“”也表示空,但是和null有很大区别:null没有分配空间,""分配了空间

string str1 = null;  //str引用为空
string str2 = "";  //str引用一个空串

null没有分配空间,""分配了空间,因此str1不是一个实例化的对象,而str2已经实例化。
注意:
因为null不是对象,""是对象,所以在进行比较时应该

 if(str1==null){...}
 if(str2.equals("")){...}
 //对象用equals比较,null用等号比较

下面写法错误:

if(str1.equals("")||str1==null){//如果str1没有值,则.... } 

正确的写法是

if(str1==null||str1.equals("")){//先判断是不是对象,如果是再判断是不是空字符串}
//str1==null为真不会判断str1.equals("");str1==null为假即str1是对象,才会判断str1.equals("")

打个比方:一个空玻璃杯不能说它里面什么都没有,因为里面有空气,当然也可以把它弄成真空,null与" "的区别就象真空与空气一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值