指针作为c的灵魂,相信已经困扰了大家很久,希望我可以带给大家一篇用人话来解说:
在C语言中,访问变量的方式有两种:
1、通过变量名访问(例如说去什么花店,以花店的名称找到对应的花店)
2、通过地址访问(通过花店的地址,导航过去)
也就是说,我们定义一个变量int a=3;那么我们可以想象有一个长方块,里面存放的数据就是3,而长方块的地址我们假设是0x77777777;
这时候定义一个指针int *p=a;那么p=&a;因此我们又可以想象有一个长方块,里面存放的就是a的地址0x77777777,而长方块的地址我们
假设为0x66666666,这就是指针的地址。int *p表示一个int型的指针变量,*p就是p这个指针里面存放的地址(0x77777777)所对应的值。
一级指针的最简单的使用情况如下:
#include
void _swap(int a, int b)
{
int temp=a;
a=b;
b=temp;
}
int main(void)
{
int a=5,b=10;
_swap(a,b);
printf("a=%d b=%d",a,b);
return 0;
}
我们想交换a,b的值,但是结果好像并不如我们所愿,因为在函数_swap中我们只是对形参进行了交换,和实际上的a,b(实参)并没有什
么联系,于是我们可以使用以下方法:
#include
void _swap(int *c,int *d)
{
int temp=*c;
*c=*d;
*d=temp;
}
int main()
{
int a=5,b=10;
_swap(&a,&b);
printf("a=%d b=%d\n",a,b);
return 0;
}
在函数_swap中我们通过传入a,b的地址,相当于让int *c=a;int d=b;那么c表示的就是他(肚子里)的地址的对应的值,也就是a的值,
这样子我们就精准的定位了实参a,b的值,对其进行改变,就不会出现上面的情况。
那么我们在什么情况下会用到二级指针呢,分析一下如下代码:
#include
using namespace std;
int a= 10;
int b = 100;
int *q;
void func(int *p)
{
cout<<"func:&p="<<&p<<",p="<<p<<endl; //note:3
p = &b;
cout<<"func:&p="<<&p<<",p="<<p<<endl; //note:4
}
int main()
{
cout<<"&a="<<&a<<",&b="<<&b<<",&q="<<&q<<endl; //note:1
q = &a;
cout<<"*q="<<*q<<",q="<<q<<",&q="<<&q<<endl; //note:2
func(q);
cout<<"*q="<<*q<<",q="<<q<<",&q="<<&q<<endl; //note:5
system("pause");
return 0;
}
请大家耐心的将所有的输出按照自己的思路模拟一下,我们发现,*q并没有像我们想的那样变成100,来一起分析一下:
{
&a=0032F000,&b=0032F004,&q=0032F228
*q=10,q=0032F000,&q=0032F228
func:&p=0018FD24,p=0032F000
func:&p=0018FD24,p=0032F004
*q=10,q=0032F000,&q=0032F228
}
note:1 a,b,q都有一个地址.
note:2 q指向a.
note:3我们发现参数p的地址变了,跟q不一样了,是的参数传递是制作了一个副本,也就是p和q不是同一个指针,但是指向的地址0x0032F000(a的地址)还是不变的.
note:4 p重新指向b.
note:5 退出函数,p的修改并不会对q造成影响。
因此,如果我们想要在函数中改变指针(肚子里)的值,而不是像之前的案例一样改变指针(肚子里)的地址的(肚子里)的值,是不可行
的,就是因为我们上面提到的参数传递是制作了一个副本,所以我们要使用二级指针:
#include
using namespace std;
int a= 10;
int b = 100;
int *q;
void func(int **p) //2
{
cout<<"func:&p="<<&p<<",p="<<p<<endl;
*p = &b; //3
cout<<"func:&p="<<&p<<",p="<<p<<endl;
}
int main()
{
cout<<"&a="<<&a<<",&b="<<&b<<",&q="<<&q<<endl;
q = &a;
cout<<"*q="<<*q<<",q="<<q<<",&q="<<&q<<endl;
func(&q); //1
cout<<"*q="<<*q<<",q="<<q<<",&q="<<&q<<endl;
system("pause");
return 0;
}
在这里我们传入的是指针q的地址,那么p(肚子里)装的就是q的地址,而q的(肚子里)装的是a的地址,我们在函数中定义了*p=&b,那
么我们让p的(肚子里)对应的值改变为b的地址,也就是改变了q所指向的地址,即q=&b。
因为传了指针q的地址(二级指针**p)到函数,所以二级指针拷贝(拷贝的是p,一级指针中拷贝的是q所以才有问题,拷贝了指针但是指针内容也
就是指针所指向的地址是不变的)所以它还是指向一级指针q(p = q)。在这里无论拷贝多少次,它依然指向q,那么p = &b;自然的就是 q = &b;了。