- 引子
什么时候使用一级指针?什么时候使用二级指针?一/二级指针对实参形参能造成什么影响?为什么链表创建,清空,删除结构体指针级别的不同造成什么样的影响?…等等宇宙大难题,至今还没搞明白,希望能通过交换变量的的例子来进一步加深对指针、全局/局部变量、以及实参形参传递方向的理解和记忆。
- 全局变量/局部变量(作用域问题)
- 关于实参形参
- 关于指针级别(略)
- 关于指针函数(?_?可能说的不对,看下方解释)
- 函数指针,函数参数为指针类型。
- 设有以下函数:
Void f(int a,char *s)
{
…;
…;
}
此处char *s 即是将指针作为函数参数来使用的。!
- 所谓指针函数,其实不应该这么叫它 因为我们已经有了指针数组,表明它是一个数组。 同理指针函数归根结底他是一个函数,是这个函数的返回值基类型为void *的指针函数,所以看如下定义:
int *fun(int,char *);//这样声明就说明他是一个函数,函数有返回值
- 关于函数指针,归根结底,他是一个指针;指针指向谁?指向函数的指针;它的作用是:将一个变量的地址传送到另一个函数中,函数名代表函数的入口地址。见如下定义
int (*fun)(int,char *);//函数指针定义
fun = f;//指针变量赋函数f()的入口地址 同样能够在初始化的时候定义。
值得注意的是:取函数的地址更不用加取地址符号”&”。注意实参与形参类型匹配。比较两者差异的细微区别就在于”()”优先级!这一点同数组指针类似 即int (*p)[10];//二维数组指针。 int *p[10] ó int (*p[10]) //指针数组。而指针函数int *fun();不是指里面的所有形参都是指针,而是指该定义的函数的返回值是int *。
下面是我在学习中遇到的问题,思考:
1.如何利用一级指针改变主调函数main()中的参数?(以交换变量值为例),显然这是不可取的?!
#include <stdio.h>
int *f(int *,int *);
int a=5,b=6;//全局变量整个程序(进程)消亡后回收
int main()
{
int *s;
int *p1 = &a , *p2 = &b;
s = f(p1,p2);
printf("a=%d\nb=%d\n*p1=%d\n*p2=%d\n*s=%d\n",a,b,*p1,*p2,*s);
//结果 为 5 6 5 6 6 天真地发现主调函数调用完后并不改变指向?
return 0;
}
int *f(int *m ,int *n)
{
int *p;
p = m;
m = n;
n = p;
return m;
}
此处,需要理解程序的死亡,函数调用完结束后空间收回,实参与形参传递问题 局部变量,全局变量作用域的问题
于是乎,我使用了二级指针 当时我就想我还是不理解上述所说的问题 ,我就用二级指针 这样我就明白函数调用 结束返回后 时个什么玩意儿 形参指针变量影不影响主调函数内实参指针变量 为什么值带不回去?(其实知者所知:当前在操作地址,只不过一个是直接寻址 另一个是间接寻址 而并未对地址指向的值操作 改变不了什么。)
#include <stdio.h>
int **f(int **,int **);
int main()
{
int a=5,b=6,**s;
int *p1 = &a , *p2 = &b;
printf("pre_a=%d\npre_b=%d\n\n",a,b);
s = f(&p1,&p2);
printf("a=%d\nb=%d\n*p1=%d\n*p2=%d\n*s=%d\n",a,b,*p1,*p2,**s);
//结果仍然为:5 6 5 6 6 ;发现二级指针在被调函数f()内的确交换了位置 并且把交换后的地址赋给了变量s
return 0;
}
int **f(int **m,int **n)
{
//int a;
//int *p1 = &a;
int **p2;
p2 = m;
m = n;
n = p2;
return m;
}
经过几许辗转反侧、看书、问同学、消耗时间 总结: 被调函数调用结束后整个函数就消亡了,而我只带回了一个地址(值) 局部变量**p2被收回(函数消亡) 如果没有一个容器s来装这个地址,那么照样无法进行址交换 ,故我现在操作的是地址 而不是地址所指向的值 仅仅交换指向 被调函数调用结束后,死亡、局部变量空间收回;程序死亡后 全局变量空间被收回。
于是 我回归到最初 其实这些老师上课都有说明! 这里仅用这个比较好的例子来更好为自己总结 ;改变了原来的想法 来看看!
#include <stdio.h>
int *f(int *,int *);
int main()
{
int a=5,b=6,*s;
int *p1 = &a , *p2 = &b;
printf("pre_a=%d\npre_b=%d\n",a,b);
s = f(p1,p2);
printf("a=%d\nb=%d\n*p1=%d\n*p2=%d\n*s=%d\n",a,b,*p1,*p2,*s);
return 0;
}
int *f(int *m ,int *n)
{
int a;
int *p = &a; //这里必须要使用一个变量来给指针变量存放地址 也是防止野指针的手段
*p = *m;
*m = *n;
*n = *p;
return m;
}
同理 二级指针操作函数来改变值,是要真正意义上的改变值,而非异想天开的想通过改变指针指向来改变指向,“指向变了 值就变了”这一说法。是作为初学者的我没理解程序运行的流程 实参形参的传递性 全局,局部,静态,创建变量而改变内存空间性质 产生的原因。(关于这块,我仍然只是理解皮毛,仍需后续进一步的通过各种程序锻炼 来理解其中的奥秘!)
#include <stdio.h>
int **f(int **,int **);
int main()
{
int a=5,b=6,**s;
int *p1 = &a , *p2 = &b;
printf("pre_a=%d\npre_b=%d\n\n",a,b);
s = f(&p1,&p2);
printf("a=%d\nb=%d\n*p1=%d\n*p2=%d\n*s=%d\n",a,b,*p1,*p2,**s);
//结果发现,与欲达到的值稳合了!!
return 0;
}
int **f(int **m,int **n)
{
int a;
int *p1 = &a;
int **p2 = &p1;
**p2 = **m;
**m = **n;
**n = **p2;
return m;
}
以上 有很多说到的知识点 没做补充说明;学才疏浅而只能为自己和相似的人做贡献。这里也有自己目前的学习见解 以交换值为例子 可以更好地解释我在做题时遇到的问题。
什么时候使用一级指针 ,什么时候使用二级指针 这也是需要去积极探索和理解的! 例如在链表中 插入 和 删除 清空 使用一级指针 二级指针 导致的结果 为什么回是这样的结果 它到底是指结点的那块地址 是我们后续需要加以积极探索的。