C/C++杂记:NULL与0的区别、nullptr的来历

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

有人喜欢使用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 0    // C++中使用0作为NULL的值
#else
# define NULL ((void *)0)    // 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) C99/C++03/C++11标准文档

(2) nullptr提案文档:N2431:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf

时间: 2024-10-11 00:26:32

C/C++杂记:NULL与0的区别、nullptr的来历的相关文章

【转载】C/C++杂记:NULL与0的区别、nullptr的来历

原文:C/C++杂记:NULL与0的区别.nullptr的来历 某些时候,我们需要将指针赋值为空指针,以防止野指针. 有人喜欢使用NULL作为空指针常量使用,例如:int* p = NULL;. 也有人直接使用0值作为空指针常量,例如:int* p = 0;. 前者可能觉得:NULL作为空指针常量,名字很形象,可读性较强. 后者可能觉得:NULL并不是C/C++语言的关键字,而是一个在标准库头文件<stddef.h>中定义的宏,因此要使用NULL,可能需要直接或简介地包含<stddef.

void ,NULL与0的区别联系

void ,NULL及0的区别联系 void的详解: void的字面意思是"无类型"或"空类型",void*则为"无针型指针",那就意味着void*可以指向任何类型的数据. 众所周知,如果指针p1和p2的类型相同,那么我们可以直接在p1和p2间互相赋值,不会出现问题:但如果p1和p2指向不同的数据类 型,则必须使用强制类型转换 运算符把赋值符号两边的类型转换为相同类型或兼容的类型,即就是把赋值运算符右边的指针类型转换为左边指针的类型. 例如: f

C/C++语言中NULL、&#39;\0’和0的区别

注:本文参考了http://blog.csdn.net/mylinx/article/details/6873253及书籍<征服C指针>([日]前桥和弥著). NULL.'\0'和0的值是一样的,都是0,不过它们的表现形式不一样: 1. NULL: 即空指针,不过在C和C++中并不一样.在VS 2013的库文件string.h中可以看到如果定义. 1 /* Define NULL pointer value */ 2 #ifndef NULL 3 #ifdef __cplusplus 4 #d

c语言NULL和0区别及NULL详解

先看下面一段代码输出什么: #include<stdo.h> int main() { int *p=NULL; printf("%s",p); } 输出<null> ,单步调试可以看出执行int *p=NULL,p的值为0x00000000,可以看出,NULL在实际底层调用中就是0, 在C语言中, NULL和0的值都是一样的,但是为了目的和用途及容易识别的原因,NULL用于指针和对象,0用于数值 对于字符串的结尾,使用'\0',它的值也是0,但是让人一看就知道

NULL, &#39;\0&#39;,0 &#39;0&#39;的区别

1.NULL; NULL 即空指针,在C和C++中的形式不一样,msdn上有如下的内容那个: #if !defined(NULL)&&defined(__NEEDS_NULL) #ifdef __cplusplus #define NULL 0 #else #define NULL ((void *)0) #endif #endif NULL 在c中用(void*)0表示,在c++中用0表示. 2.'\0' '\0'表示字符串结束,它在ASCII中的值为0(数值0,非字符‘0’) 所以在数

NULL、0、nullptr 区别分析

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 *是不能隐式转换成其他指针类型的,所以通

C/C++ 中 NULL、&#39;\0&#39;、&#39;0&#39; 、0、及空格的区别

1.NULL即空指针.在C中,NULL是指向0的指针,由 #define NULL ((void *)0)定义:在C++中,NULL就是0,由 #define NULL 0 定义.可参见 vs2013 的库文件 string.h. 2.'\0' 是空字符常量,表示字符串的结束,ASCII码值为0. 3.'0'是字符0,ASCII码值为48. 4.0是数字0. 5.空格是可显示字符空格,ASCII 码值为32. 备注: 给指针置位为空指针时,应该使用 NULL: 给字符串添加结束标志时,应该使用

php中0,空,null和false的区别

<? $str1 = null; $str2 = false; echo $str1==$str2 ? ‘相等’ : ‘不相等’; $str3 = ""; $str4 = 0; echo $str3==$str4 ? ‘相等’ : ‘不相等’; $str5 = 0; $str6 = '0'; echo $str5===$str6 ? ‘相等’ : ‘不相等’; $str7=0; $str=false; echo $str7==$str8 ? ‘相等’ : ‘不相等’; ?>

href=#与href=javascriptvoid(0)的区别

#"包含了一个位置信息 默认的锚点是#top 也就是网页的上端 而javascript:void(0)  仅仅表示一个死链接 这就是为什么有的时候页面很长浏览链接明明是#可是跳动到了页首 而javascript:void(0) 则不是如此 所以调用脚本的时候最好用void(0) 或者<input onclick> <div onclick>等 打开新窗口链接的几种办法 1.window.open('url') 2.用自定义函数 <script>