Pointer's NULL And 0
问题起源
在使用Qt框架的时候, 经常发现一些构造函数 *parent = 0
这样的代码. 时间长了, 就觉的疑惑了. 一个指针不是等于NULL
吗? 这样写, 行得通吗? 自己测试一下就可以了.
测试代码
#include <iostream>
using namespace std;
int main()
{
int * npt = 0;
if( 0 == npt ){
cout << "npt == 0" << endl; ///< 输出
}
if( NULL == npt ){
cout << "npt == NULL" << endl; ///< 输出
}
char * cpt = NULL;
if( 0 == cpt ){
cout << "cpt == 0" << endl; ///< 输出
}
if( NULL == cpt ){
cout << "cpt == NULL" << endl; ///< 输出
}
return 0;
}
调试结果
npt 0x0 int* 看到,指针的value是个16进制的0.
结果分析
四句if的判断都有输出. 也就是说0
和NULL
是没有区别的. 难道NULL这个宏的数值就是0. Qt IDE中的NULL
宏代码如下:
/* A null pointer constant. */
#if defined (_STDDEF_H) || defined (__need_NULL)
#undef NULL //in case <stdio.h> has defined it.
#if defined(__GNUG__) && __GNUG__ >= 3
#define NULL __null
#else //G++
#ifndef __cplusplus
#define NULL ((void *)0)
#else //C++
#ifndef _WIN64
#define NULL 0
#else
#define NULL 0LL
#endif //W64
#endif //C++
#endif //G++
#endif //NULL not defined and <stddef.h> or need NULL.
#undef __need_NULL
NULL
确实有0这么一说.
权威文档
接着看一下cplus的null介绍:
- C: A null-pointer constant is an integral constant expression that evaluates to zero (like 0 or 0L), or the cast of such value to type void* (like (void*)0).
- C++98: A null-pointer constant is an integral constant expression that evaluates to zero (such as 0 or 0L).
- C++11 : A null-pointer constant is either an integral constant expression that evaluates to zero (such as 0 or 0L), or a value of type nullptr_t (such as nullptr).
A null pointer constant can be converted to any pointer type (or pointer-to-member type), which acquires a null pointer value. This is a special value that indicates that the pointer is not pointing to any object
再次疑惑
为什么是0 ? 0有什么特殊含义吗? 什么时候用0? 什么时候用MULL?
路人观点
路人甲
看<高质量C编程>:指针变量的零值是“空” (记为 NULL ) 。尽管 NULL 的值与 0 相同,但是两者意义不同。假设指针变量的名字为 p ,它与零值比较的标准 if 语句如下:
if (p == NULL) // p 与 NULL 显式比较,强调 p 是指针变量
if (p != NULL)
不要写成
if (p == 0) // 容易让人误解 p 是整型变量
if (p != 0)
或者
if (p) // 容易让人误解 p 是布尔变量
if (!p)
我想说, 我一般不会这样命名...
路人乙
由于c++收紧的类型检查规则,使用普通的0而不是NULL带来的问题会少一点,如果你觉得一定要用NULL,使用
const int NULL = 0;
0 是任何平台都通用的,而NULL有可能重定义。
实际的情况是 0 是任何平台都通用的,有没有那个系统不把0当保留地址???,而NULL有可能重定义。 类的默认构造函数中需把指针变量初始化,如果写NULL的话必须先在头文件中定义NULL,或是包含相关的库,这就可能带来问题。 c++11,统一为nullptr . 在c语言环境下,由于不存在函数重载等问题,直接将NULL定义为一个void的指针就可以完美的解决一切问题。但是在c++环境下情况就变得复杂起来, 首先我们不能写这样的代码FILE* fp = (void*)0;
将void直接赋值给一个指针是不合法的,编译器会报错。 我们只能这样写代码
FILE* fp = (FILE*)0;
// or
FILE* fp = 0;
所以在c++下面,NULL就被直接定义为一个整型 0。 在大多数情况下这并不会产生什么问题,但是万一有重载或者模板推导的时候,编译器就无法给出正确结果了。比如下面的情形:
void call_back_process(CCObject* target, void* data);
bind(call_back_process, target, NULL); // error 函数类型是void* ,但是我们绑定的是一个整型 0
所以 C倾向于NULL, C++倾向于0, 更新的C++倾向与nullptr.
嗯...,也就是说, 分语言考虑了.
路人丙
google提的建议是为了他们自己的需求而设计的, 不同的场合下, 编程规范会不同, 是正常的. 编程规范不是坏东西,反对“教条化”也不是坏事. 但是在反对那些大师的“教条”前先问问自己, 是否明白了那些建议及教条背后的理由? 自己是否有足够充分的理由不听从对方的建议? 你在google预设的环境下使用NULL不会出问题, 不代表在其他环境下不会出问题,因为标准沒有给予你任何保证, 但是使用0不会出错却是标准给予的保证. 考虑到可移植性,我会选择0而不是NULL. 虽然使用NULL在大部分环境下都不会出事,但是这毕竟是不被标准支援的行为. 所以c++11又引入了一个关键字--nullptr. 直接用nullptr就好了,保证安全,而且意义清楚,也方便overload.
void f(char const \*ptr); // \*为markdown转义
void f(int v);
f(NULL); //which function will be called?
f(nullptr); //first function is called
很厉害的说服力...
路人丁
C++如果重载int版本和地址版本,实参用NULL总是调用int版本
#include <iostream>
void foo(int){}
void foo(int*){}
int main()
{
foo(0); ///< foo(int)
foo(NULL); ///< foo(int),NG
foo((int*)0); ///< foo(int*)
foo(nullptr); ///< foo(int*), C++ 0x
return 0;
}
重载的时候, 需要考虑一下...
我的决定
对于, 婆说婆有理, 每个人都很对. 我的决定是, 问问领导, 问问团队的人员使用的什么. 和自己的开发团队保持一致就可以了. ( 没想到, 本来一个很小的疑惑, 引出来这么多的考虑. 烦死了... )
参考引用
Pointer's NULL And 0的更多相关文章
- 《征服 C 指针》摘录1:什么是空指针?区分 NULL、0 和 '\0'
一.什么是空指针? 空指针 是一个特殊的指针值. 空指针 是指可以确保没有向任何一个对象的指针.通常使用宏定义 NULL 来表示空指针常量值. 空指针 确保它和任何非空指针进行比较都不会相等,因此经常 ...
- C/C++语言中NULL、'\0’和0的区别
注:本文参考了http://blog.csdn.net/mylinx/article/details/6873253及书籍<征服C指针>([日]前桥和弥著). NULL.'\0'和0的值是 ...
- 【转载】C/C++杂记:NULL与0的区别、nullptr的来历
原文:C/C++杂记:NULL与0的区别.nullptr的来历 某些时候,我们需要将指针赋值为空指针,以防止野指针. 有人喜欢使用NULL作为空指针常量使用,例如:int* p = NULL;. ...
- c语言NULL和0区别及NULL详解
先看下面一段代码输出什么: #include<stdo.h> int main() { int *p=NULL; printf("%s",p); } 输出<n ...
- 字符数组和string判断是否为空行 NULL和0 namespace变量需要自己进行初始化
string 可以这样判断空行input !="" 字符数组可以通过判断第一个元素是否为空字符'\0',是的话为空行arrar[0]=='\0':或者用长度strlen(char ...
- unity, Graphics.Blit (null, null, mat,0);
我使用 Graphics.Blit (null, finalRT, mat); 合成出一张finalRT,然后将finalRT用在editor脚本的OnInspector中使用 Graphics.Dr ...
- c++11 NULL、0、nullptr
C的NULL 在C语言中,我们使用NULL表示空指针,也就是我们可以写如下代码: int *i = NULL;foo_t *f = NULL; 实际上在C语言中,NULL通常被定义为如下: #de ...
- 史上最明白的 NULL、0、nullptr 区别分析(老师讲N篇都没讲明白的东东),今天终于明白了,如果和我一样以前不明白的可以好好的看看...
C的NULL 在C语言中,我们使用NULL表示空指针,也就是我们可以写如下代码: int *i = NULL; foo_t *f = NULL; 实际上在C语言中,NULL通常被定义为如下: #def ...
- NULL 和 0
Question: What is the difference from NULL and "0"? Example: return NULL; return 0; Answer ...
随机推荐
- Spring集成JUnit测试
1.程序中有Junit环境2.导入一个jar包.spring与junit整合jar包 spring-test-3.2.0.RELEASE.jar3.测试代码 @RunWith(SpringJUnit4 ...
- shell处理输入
1.在运行脚本时指定参数,直接在脚本名称后边跟随需要添加的参数,在运行的过程中,$0代表程序名,$1代表第一个参数,$2代表第二个参数,一直到第九个,从第十个参数开始需要变成${10}等,即需要添加花 ...
- BZOJ 3144 [Hnoi2013]切糕 ——网络流
[题目分析] 网络流好题! 从割的方面来考虑问题往往会得到简化. 当割掉i,j,k时,必定附近的要割在k-D到k+D上. 所以只需要建两条inf的边来强制,如果割不掉强制范围内的时候,原来的边一定会换 ...
- 任务栏显示进度条 CreateComObject(CLSID_TaskbarList) as ITaskbarList4
http://www.cnblogs.com/jxsoft/archive/2011/06/02/2067712.html //在任务栏显示 进度条 unit Unit9; interface use ...
- 关于UnsupportedClassVersionError的错误处理
错误:Java.lang.UnsupportedClassVersionError: Bad version number in .class file 造成这种错误的原因是你的支持Tomcat运行的 ...
- Windows安装程序 报错 “已安装了较新版本” 导致无法安装程序的解决方法
打开注册表 HKEY_CURRENT_USER\Software\Microsoft\Installer\Products ,“查找”程序名称 如果有程序名和安装程序相同的 ,删除整个 项 ! 然后就 ...
- SOAPUI使用教程-了解REST参数
1.2.资源参数 在这一节中,我们更为详细的看看提供给你不同类型的REST参数.有五种类型的可用参数:QUERY, HEADER, TEMPLATE, MATRIX and PLAIN. 所有参数可以 ...
- python 基础之数据类型
一.python中的数据类型之列表 1.列表 列表是我们最以后最常用的数据类型之一,通过列表可以对数据实现最方便的存储.修改等操作 二.列表常用操作 >切片>追加>插入>修改& ...
- Android 腾讯入门教程( 智能手表UI设计 和 MVC模式 )
*****注意到mvc 在android 中是如何进行分层分域执行各自的功能.**** 官方推荐的按钮尺寸是48像素 前端之Android入门(1):环境配置 前端之Android入门(2):程序目录 ...
- Redis 主从配置
环境 Master/Slave 系统 IP Redis版本 Master CentOS6.7 10.10.3.211 redis-3.2.6 ...