
先看一段代码#include iostream using namespace std; void func(char* p) { cout void func(char* p) endl; cout p endl; } void func(int p) { cout void func(int p) endl;; cout p endl; } int main() { //int func(10); //char* func(NULL); //这里我希望程序调用func(char* p)的函数 system(pause); return 0; }输出结果void func(int p) 10 void func(int p) 0调用了两次func(int p)函数且按理说NULL指针是不能cout的也就是说第二次调用func(NULL)也调用了一次func(int p) 并且传入的p是0原因在底层源码中NULL这个宏是这样定义的#ifndef NULL #ifdef __cplusplus #define NULL 0 #else #define NULL ((void *)0) #endif #endif也就是说如果源码是C程序NULL就是0如果是C程序NULL表示(void*)0。那么为什么要这样做呢是由于 C 中void * 类型无法隐式转换为其他类型的指针此时使用 0 代替 ((void *)0)用于解决空指针的问题。这个00x0000 0000表示的就是虚拟地址空间中的0地址这块地址是只读的。正如C98/03 标准中将一个指针初始化为空指针的方式有 2 种char *ptr 0; char *ptr NULL;并且int* ptr1 NULL; char* ptr2 NULL; double* ptr3 NULL; void* ptr4 NULL; int* ptr5 ptr4;//报错void*类型的值不能用于初始化int*类型的实体 //是由于 C 中void * 类型无法隐式转换为其他类型的指针此时使用 0 代替 ((void *)0)用于解决空指针的问题。 int* ptr5 (int*)ptr4; //强转正确不报错C11引入nullptr关键字用于标识空指针是std::nullptr_t类型的constexpr变量。它可以转换成任何指针类型和bool布尔类型主要是为了兼容普通指针可以作为条件判断语句的写法但是不能被转换为整数。nullptr是专用于初始化空类型指针不同类型的指针变量都可以使用 nullptr 来初始化nullptr 出现的目的是为了替代 NULL#include iostream using namespace std; void func(char* p) { cout void func(char* p) endl; //cout *p endl; } void func(int p) { cout void func(int p) endl;; //cout p endl; } int main() { int* ptr1 nullptr; char* ptr2 nullptr; double* ptr3 nullptr; void* ptr4 nullptr; int* ptr5 (int*)ptr4; //int func(10); //char* func(nullptr); system(pause); return 0; }输出结果void func(int p) void func(char* p)通过输出的结果可以看出nullptr 无法隐式转换为整形但是可以隐式匹配指针类型。在 C11 标准下相比 NULL 和 0使用 nullptr 初始化空指针可以令我们编写的程序更加健壮因此当需要使用 NULL 时候养成直接使用 nullptr的习惯。