指针(指针作为输出型参数)与结构体指针作为函数参数(树),以及函数内存

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39642794/article/details/78975031

点击打开链接

#include<stdio.h>
#include<stdlib.h>
void swap(int *b)
{
printf("%p\n",b);
printf("%p\n",&b);
b=(int *)malloc(sizeof(int));
printf("%p\n",b);
printf("%p\n",&b);
}
int main()
{
int a=4;
printf("%p\n",&a);
swap(&a);
  //  printf("%p\n",&a);
return 0;
}

输出结果为:000000000065FE4C
                    000000000065FE4C
                    000000000065FE20
                    0000000000B813D0
                    000000000065FE20

说明:函数实参(传递得是地址)和形参共享一片内存,所以你改变地址里储存的值(不是改变地址),函数外也随之改变。但是如果在函数内新开辟一块内存(b=(int *)malloc(sizeof(int));),形参的地址也随之改变,此时形参和实参地址不一样,所以你改变形参里面的值,函数外面不能随之改变,而且在函数里开辟的内存(动态存储)在函数执行完毕后就释放了,形参的值在函数结束后就不存在了。

所以引出下面的问题:

void createtree(bitree *p)

{
char ch;
scanf("%c",&ch);
if(ch=='#') 
*p=NULL;
else
{
*p=(bitree)malloc(sizeof(binode));
(*p)->data=ch;
createtree(&((*p)->lchild));
   createtree(&((*p)->rchild));
}
}
建立二叉树为什么要用双指针(没有返回值的情况),因为用单指针,你给它开辟了一块内存,形参和实参的地址早就不一样了,故形参的改变不会让函数外的指针变化。所以用双指针,开辟内存后,只是改变(*p),没有改变p,也就是改变p指向值,没有改变p的值(p是指针变量,也就是地址)。(类似于 void swap(int *b))。
       从函数的单项传递(可以改变实参指针变量所指向变量的值,不可能改变实参指针变量的值)上看,单指针在函数调用中,如果开辟一块新的内存,相当于改变了指针变量的值(地址),开辟内存用双指针就相当于改变实参指针变量所指向变量的值。
       最后一个问题:void inthreading(bitree p3)// 
{
if(p3)
{
inthreading(p3->lchild);
if(!p3->lchild){p3->ltag=thread;p3->lchild=pre;}//前驱索化 
else p3->ltag=link;
if(!pre->rchild){pre->rtag=thread;pre->rchild=p3;}// 后继索化 
else
pre->rtag=link;
pre=p3;
   inthreading(p3->rchild);
}
}(完整函数见线索二叉树)

       为什么这个函数用单指针无返回值,然后将叶子结点左右指针分别指向前驱和后继,函数结束后,为什么能保存下来。我陷入误区,感觉p->rchild=p是改变了p指针变量的值(违背函数单项传递性),其实p指向的内容的值包括data(数据域)和指针域(next),所以p->rchild=p只是改变了改变实参指针变量所指向变量的值,故并没有违背。

总之一句话:函数中里开辟内存,想让函数外也接受到(不用返回值),就把函数里开辟的内存变成形参指针变量指向的变量的值(故双指针)。

猜你喜欢

转载自blog.csdn.net/qq_39642794/article/details/78975031