学习了一学期c语言后,对一级指针做函数参数的操作自以为已经相当熟练,不会出现程序崩溃的情况,但是在昨天用二级指针做函数参数的时候发现自己的一级指针好菜…
问题如下
void a(int *p)
{
int m=5;
p=&m;
printf("%d\n",*p);
}
int main()
{
int *s;
int n=6;
s=&n;
printf("%d\n",*s);
a(s);
printf("%d\n",*s);
}
在这段代码里,用一个一级指针p做形参,将指针s做实参进行参数传递,本以为这样做可以改变指针s的原指向关系,即预期结果是s由指向n变为指向m,从而最后一句输出语句结果为5。但是运行代码后结果如下
可见形参p确实指向了m并且输出为5,但是调用a()函数结束后s依旧指向n且输出为6。
也就是说通过a()函数并没有改变s的指向关系。
通过分析发现,当s作为实参传递的时候,系统会在调用函数a()时自动为形参p分配一段临时空间,此时p指向s,执行语句p=&m后,p作为一个不同于指针s的指针指向m,但指针s的原指向关系并未发生改变,函数调用结束后释放形参p及函数所占空间。画一张图理解一下。
所以由此便牵扯到了另一个问题,咳咳,敲黑板。划重点!!!
void temp(char *p,int n)
{
p=(char*)malloc(sizeof(char)*n);
strcpy(p,"hello");
puts(p);
//printf("%x\n",p);//输出地址
return;
}
int main()
{
char *s;
temp(s,10);
puts(s);
// printf("%x\n",s);//输出地址
return 0;
}
上述代码的运行结果是什么呢?两次puts()究竟会不会输出内容?
1秒钟时间思考一下。
结果如下
很显然,temp()函数中成功用malloc()函数为字符串指针p分配内存空间,且成功输出字符串"hello",而函数结束后puts(s)并没有得到结果。
原因已经说过了,函数内只会对临时指针变量p进行操作,当然分配的空间也是为p分配,s并没有得到任何空间,puts(s)是不会得到结果的。
再对指针p和s指向的地址进行输出,结果如下
s仍然指向NULL(0)。
这里还有一个很重要的知识点提一下,使用malloc()函数为指针变量分配内存空间后,一定要及时free()释放,否则会造成内存泄露,具体百度。
那如何实现用指针参数申请内存,既然一级指针无法做到,那就用“指针的指针”----二级指针
一级指针变量用来存储指向方块的地址,同理
二级指针变量p用来存储一级指针变量的地址,且只能存储一级指针变量的地址。
例如
int main()
{
int **p,*t,m=5;
t=&m;
p=&t;
printf("%d %d %d\n",**p,*t,m);
return 0;
}
输出结果
5 5 5
画个图理解一下。
分别输出一下p,&t,*p,t,&m看一下结果
printf("%x %x %x %x %x\n",p,&t,*p,t,&m);
总结:二级指针变量p存储一级指针变量t的地址,故p==&t都为60ff08
对二级指针变量p进行一次取值运算*p,
得到一级指针变量t存储的内容,即指向的m的地址,故*p==t==&m都为60ff0c
问题又回到如何实现用指针参数申请内存
将上述代码修改成这样
void temp(char **p,int n)
{
*p=(char*)malloc(sizeof(char)*n);
strcpy(*p,"hello");
puts(*p);
printf("%x\n",*p);//输出地址
return;
}
int main()
{
char *s;
temp(&s,10);
puts(s);
printf("%x\n",s);//输出地址
return 0;
}
运行结果
其中**p是临时二级指针变量,故能存储一级指针变量s的地址,所以调用temp()函数时用&s而不用s,temp()函数内部对*p进行操作实际是对字符串指针s进行操作。
详细看博客https://www.cnblogs.com/dingou/p/5937024.html