一、NULL与0
在C和C++中,NULL和0都可以使用。
C通常使用NULL,C++通常使用0
#include <stdio.h>
int main(void) {
int *p=NULL;
int *q=0;
printf("%d %d",p,q);
//0 0
return 0;
}
#include <iostream>
using namespace std;
int main() {
int *p=NULL;
int *q=0;
cout<<p<<" "<<q<<endl;
//0 0
return 0;
}
问:NULL到底是什么?
答:NULL是一个宏。
问:它的值是多少?
答:C/C++标准规定:它的值是一个空指针常量(null pointer constant),由实现定义。
NULL宏是如何定义的?
答:以gcc或clang编译器为例,NULL的定义大致如下(稍有简化):
#if defined(__cplusplus) # define NULL 0 // C++中使用0作为NULL的值 #else # define NULL ((void *)0) // C中使用((void *)0)作为NULL的值 #endif
问:什么样的值才能称之为空指针常量?
答:C语言中常数0和(void*)0都是空指针常量;C++中(暂且忽略C++11)常数0是,而(void*)0 不是
问:为什么C中(void*)0是空指针常量,而C++中不是?
答:因为C语言中任何类型的指针都可以(隐式地)转换为void*型,反过来也行。而C++中void*型不能隐式地转换为别的类型指针(例如:int*p = (void*)0;使用C++编译器编译会报错)
二、nullptr
nullptr是C++独有的,nullptr还是C++的一个关键字。
C++引入nullptr是为了解决NULL为0,判断其是指针还是int类型的歧义
#include <stddef.h>
void foo(int) {} // #1
void foo(char*) {} // #2
int main() {
foo(NULL);
//C++会调用#1,认为NULL是0,是int
}
void foo(int) {} // #1
void foo(char*) {} // #2
int main() {
foo(nullptr);
//它会毫无异议地调用#2
}
三、NULL的例题
在C/C++中,NULL的地址均不可访问,也就是不能取出NULL代表的地址上的值
int *p=NULL;
int a=*p;
//error
一个访问NULL地址出错的考题:
解析:main()里的node调用fun()函数,传入参数node,fun()里的node其实是传递指针,int *node=node,前者node是fun()作用域里的指针,后者是main()作用域里的指针。fun()里改变fun()作用域的node的指向,可以输出100。但回到main()时,因为它改变的是指针的指向,而不是指针的值(指针的传递知识:https://blog.csdn.net/sandalphon4869/article/details/88758680),所以改变不可以被传递,即fun()里的fun()作用域的node由于是局部变量被释放,main()里的main()作用域的node其实没有任何改变,还是指向NULL,访问出错。
#include <stdio.h>
void fun(int *node)
{
int N=100;
node=&N;
printf("%d\n",*node);
//100
}
int main()
{
int *node=NULL;
fun(node);
printf("%d\n",*node);
//error
return 0;
}
改变传递的指针的值解决错误:
解析:改变传递的指针的指向不可以传递改变,而改变传递的指针的值则可以传递改变。
#include <stdio.h>
void fun(int *&node)
{
int N=100;
node=&N;
}
int main()
{
int *node=NULL;
fun(node);
printf("%d\n",*node);
//100
return 0;
}
使用二级指针解决错误:
解析:int **node是一个二级指针,fun(&node)传递的是node的地址。fun()里**node是&node,即node本身变量名存储的地址,*node是node的指向的地址,让node指向了100,因为*node是改变指针的值,所以改变可以被传递。
#include <stdio.h>
void fun(int **node)
{
int N=100;
*node=&N;
}
int main()
{
int *node=NULL;
fun(&node);
printf("%d\n",*node);
//100
return 0;
}
使用引用操作符:
解析:引用改变的被传递的参数
#include <stdio.h>
void fun(int *&node)
{
int N=100;
node=&N;
}
int main()
{
int *node=NULL;
fun(node);
printf("%d\n",*node);
//100
return 0;
}
参考: