在Clang 6.0 的stddef.h文件中可以找到NULL和nullptr的声明:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#undef NULL#ifdef __cplusplus# if !defined(__MINGW32__) && !defined(_MSC_VER)# define NULL __null# else# define NULL 0# endif#else# define NULL ((void*)0)#endif#ifdef __cplusplus#if defined(_MSC_EXTENSIONS) && defined(_NATIVE_NULLPTR_SUPPORTED)namespace std { typedef decltype(nullptr) nullptr_t; }using ::std::nullptr_t;#endif#endif |
早在1972年,C语言诞生的初期,常数0带有常数及空指针的双重身分。 C使用preprocessor macro NULL表示空指针,让NULL及0分别代表空指针及常数0。 NULL可被定义为((void*)0)或是0。
C++并不采用C的规则,不允许将void*隐式转换为其他类型的指针。为了使代码char* c = NULL;能通过编译,NULL只能定义为0。这样的决定使得函数重载无法区分代码的语义:
|
1
2
|
void foo(char *);void foo(int); |
C++建议NULL应当定义为0,所以foo(NULL);将会调用foo(int),这并不是程序员想要的行为,也违反了代码的直观性。0的歧义在此处造成困扰。
C++11引入了新的关键字来代表空指针常数:nullptr,将空指针和整数0的概念拆开。 nullptr的类型为nullptr_t,能隐式转换为任何指针或是成员指针的类型,也能和它们进行相等或不等的比较。而nullptr不能隐式转换为整数,也不能和整数做比较。
为了向下兼容,0仍可代表空指针常数。
|
1
2
3
4
5
|
char* pc = nullptr; // OKint * pi = nullptr; // OKint i = nullptr; // error foo(pc); // 呼叫foo(char *) |
PS:__MINGW32__是MinGW编译器的预定义宏。_MSC_VER是微软C/C++编译器——cl.exe 编译代码时预定义的一个宏。_MSC_VER的值表示cl的版本。需要针对cl特定版本编写代码时,也可以使用该宏进行条件编译。
本文探讨了C语言中NULL的历史背景及其在C++中的发展,特别是C++11引入的新关键字nullptr。文章详细解释了nullptr如何解决传统NULL定义带来的问题,并展示了nullptr在代码中的使用方式。
2948

被折叠的 条评论
为什么被折叠?



