首先需要知道C中的NULL是什么,它在stdio.h头文件中进行了定义 #define NULL 0,即表示NULL是一个符号常量,代表整数0。
int *p;
p=NULL;
p=NULL,即p是空指针,此时指针变量p指向地址为0的单元,系统保证该单元不作它用(不存放有效数据)。
空指针不会指向任何对象,不应该对空指针进行解引用操作。如果不小心对空指针进行解引用并且对其进行赋值,编译阶段可能会给予通过,但程序运行时会出现错误,甚至让程序崩溃
下面是对空指针进行解引用的错误案例以及解决办法,该代码想要实现使*p等于i的值10(不止一处错误,可以一步一步看):
#include <stdio.h>
void modify_pointer(int *p, int *q) {
p = q;
}
int main() {
int *p = NULL;
int i = 10;
int *q = &i;
modify_pointer(p, q);
printf("after modify_pointer *p=%d\n", *p);
return 0;
}
上述代码运行结果是:
进程已结束,退出代码为 -1073741819 (0xC0000005)
很明显,代码没有运行成功,原因是经过modify_pointer函数后,指针变量p的值并没有得到改变,程序运行到上面 printf 处崩溃了,因为此时指针变量p仍指向地址为0的单元,而这个单元不存放有效数据,是无法进行访问的,即地址为0的单元是无法进行访问的。
而经过经过modify_pointer函数后,指针变量p的值并没有得到改变的原因是:
C语言中实参变量和形参变量之间的数据传递是单向的‘值传递’方式,指针变量作为函数参数同样也遵循这一规则。
虽不可以通过执行调用函数来改变实参指针变量的值,但可以改变实参指针变量所指变量的值。如果把代码改一下
#include <stdio.h>
void modify_pointer(int *p, int *q) {
*p = *q; //想将指针变量q所指的变量i的值赋给指针变量p所指内容
}
int main() {
int *p = NULL;
int i = 10;
int *q = &i;
modify_pointer(p, q);
printf("after modify_pointer *p=%d\n", *p);
return 0;
}
但是在此时的运行如下,结果还是不行
进程已结束,退出代码为 -1073741819 (0xC0000005)
此时该程序是运行到函数modify_pointer中的*p = *q语句时崩了(经过调试得知)
原因如下:
void modify_pointer(int *p, int *q) {
*p = *q;
}
modify_pointer函数中*p = *q语句,是想将指针变量q所指的变量i的值赋给指针变量p所指内容,但是我们知道指针变量p存放的是符号常量NULL,而且该符号常量NULL内容为0,即p存的地址是0,系统规定该地址0上的单元不存放有效数据,此时你想将指针变量q所指的变量i的值(一个有效数据)放到这里面,程序就崩溃了(为什么地址为0的单元上不能存放有效数据可能涉及更深层的原因,感兴趣的可以搜搜)
如果这样的话就可以了,让指针变量p的初始化值不为NULL:
#include <stdio.h>
#include <stdlib.h>
void modify_pointer(int *p, int *q) {
*p = *q;
}
int main() {
int *p;
p=(int *) malloc(sizeof(int)*4);
int i = 10;
int *q = &i;
modify_pointer(p, q);
printf("after modify_pointer *p=%d\n", *p);
free(p); //申请的空间不使用后记得要free一下
return 0;
}
运行结果为:
after modify_pointer *p=10
也可以利用二级指针,直接改变指针变量p所指向的值,这里面modify_pointer(&p,q)中的&p,是对一级指针取地址,此时&p变成了二级指针(指向指针的指针),
#include <stdio.h>
void modify_pointer(int **p, int *q) {
*p = q;
}
int main() {
int *p = NULL;
int i = 10;
int *q = &i;
modify_pointer(&p, q);
printf("after modify_pointer *p=%d\n", *p);
return 0;
}
运行结果为:
after modify_pointer *p=10
或者C++中的引用:
#include <stdio.h>
void modify_pointer(int *&p, int *q) {
p = q;
}
int main() {
int *p = NULL;
int i = 10;
int *q = &i;
modify_pointer(p, q);
printf("after modify_pointer *p=%d\n", *p);
return 0;
}
运行结果:
after modify_pointer *p=10