指针就是内存地址,内存地址就是指针
举个栗子来学习指针:
#include<stdio.h>
#include<stdlib.h>
main(){
int i=10;
int* p;//定义一个一级指针p
p=&i;//把i对应的内存地址,赋值给p
printf("*p取得的值是:%d\n\n",*p); //*p就是取值,就是把p对应的那个内存地址的值取出来
system("pause");
}
结果是这样的:
但是要注意一点的是:
p=&i;
这一句代码,在C语言中是把i的内存地址,给了p。
画张图来分析一下:
那么由此可见,i的内存地址给了p之后,那p取得的值自然就是i的内存地址对应的那个值啦~
这里有4个问题:
- 修改i,p的取值有无变化?p的内存地址有无变化?
#include<stdio.h>
#include<stdlib.h>
main(){
int i=10;
int* p=&i;
printf("修改i前,*p取得的值是:%d\n\n",*p);
i=100;
printf("修改i后,*p取得的值是:%d\n\n",*p);
system("pause");
}
得到的结果是:
我们来分析分析,int* p=&i这句话,我们在上文已经分析过,其实就是把i的内存地址赋给了p,那么p打印出来的值,就是i对应的内存的地址的值,所以最初p打印的值,是i的值——10,而后,直接将i对应的内存地址的值改成了100,那等价关系推出来,自然p的值,也会变成100了。
我们再打印一下,i和p的内存地址,也可以很直观的看出来内存地址结果:
可以看到,对i直接赋值,i的内存地址虽然改变了,但是p的内存地址没有改变,换而言之,只是p的值即p对应的值的内存地址改变了,并不影响p本身的内存地址。所以,由此得到结论,改变i的值,对p的值有影响,而对p的本身的内存地址无影响。
- 修改p,i的取值有无变化?i的内存地址有无变化?
#include<stdio.h>
#include<stdlib.h>
main(){
int i=10;
int* p=&i;
printf("修改p前,i取得的值是:%d\n\n",i);
int j=100;
p=&j;
printf("修改p后,i取得的值是:%d\n\n",i);
system("pause");
}
得到的结果是:
修改p前,i取得的值是:10
修改p后,i取得的值是:10
注意这两行代码:
int j=100;
p=&j;
看图分析:
可以看到,改变p的值,即是改变了p的值对应内存,使它指向了j的内存地址,但是对i是毫无影响的。所以,改变p的值,i的值没有影响,i的内存地址也没有影响。
- 修改*p的值,对i的取值有没有影响?对i的内存地址有没有影响?
#include<stdio.h>
#include<stdlib.h>
main(){
int i=10;
int* p=&i;
printf("修改*p前,i取得的值是:%d\n\n",i);
*p=100;
printf("修改*p后,i取得的值是:%d\n\n",i);
system("pause");
}
运行这些代码过后,可以看到有如下结果:
修改*p前,i取得的值是:10
修改*p后,i取得的值是:100
可以看到,这个结果跟第1个问题的结果一样,那么这是为什么呢。在最开始的栗子里我们注释过,*p就是取值,就是把p对应的那个内存地址的值取出来,而在对*p重新赋值之前,实际上,是将i的内存地址给了p,那么*p其实取的就是i的内存地址对应的值,那么这个时候,如果对*p重新赋值,换句话说,就是对i的内存地址重新赋值,那么自然的,i的取值就会改变,而i的取值变了,i的内存地址也是会有影响的。
- 指针中,如何互换两个数?
一般,我们的代码都会这样写:
#include<stdio.h>
#include<stdlib.h>
main(){
int a=10;
int b=20;
printf("互换前,a是:%d\n",a);
printf("互换前,b是:%d\n\n",b);
int temp=a;
a=b;
b=temp;
printf("互换后,a是:%d\n",a);
printf("互换后,b是:%d\n\n",b);
system("pause");
}
那么运行的结果,两个数也确实进行了交换:
然而为了代码的实用性,我们一般会将互换的逻辑提取出来写成一个函数,以便供后面使用,这个时候,我们一般会将代码写成这个样子:
#include<stdio.h>
#include<stdlib.h>
void change(int a,int b){
int temp=a;
a=b;
b=temp;
}
main(){
int a=10;
int b=20;
printf("互换前,a是:%d\n",a);
printf("互换前,b是:%d\n\n",b);
change(a,b);
printf("互换后,a是:%d\n",a);
printf("互换后,b是:%d\n\n",b);
system("pause");
}
乍一看,没问题,毕竟我们在java中,也是直接将公共部分提取出来,那么运行上面的代码,得到的是一个怎样的结果呢:
运行过后发现,a的值和b的值,并没有交换,这是为什么呢?在C语言中,传值是无法改变值的。我们来打印a和b的地址来分析一下:
#include<stdio.h>
#include<stdlib.h>
void change(int a,int b){
int temp=a;
a=b;
b=temp;
printf("互换后,a的内存地址是:%#x\n",&a);
printf("互换后,b的内存地址是:%#x\n\n",&b);
}
main(){
int a=10;
int b=20;
printf("互换前,a是:%d\n",a);
printf("互换前,b是:%d\n\n",b);
printf("互换前,a的内存地址是:%#x\n",&a);
printf("互换前,b的内存地址是:%#x\n\n",&b);
change(a,b);
printf("互换后,a是:%d\n",a);
printf("互换后,b是:%d\n\n",b);
system("pause");
}
可以看到,互换前后,a和b的地址,根本就不是同一个地址了。那么这是为什么呢?画个图来分析一下:
在上面的代码中,我们是把转换的逻辑提出来成为了一个change()函数,那么这就意味着,change()函数里面的int a、int b和main()函数中的int a、int b根本就不是同一个,虽然它们长的一样且值一样,但是它们的本质,已然不是同一个。
如果要想将值真正的转换,我们就应该将a和b的地址传过去:
#include<stdio.h>
#include<stdlib.h>
void change(int* a,int* b){
int temp=*a;//取a对应的值赋值
*a=*b;
*b=temp;
printf("互换后,a的内存地址是:%#x\n",a);
printf("互换后,b的内存地址是:%#x\n\n",b);
}
main(){
int a=10;
int b=20;
printf("互换前,a是:%d\n",a);
printf("互换前,b是:%d\n\n",b);
printf("互换前,a的内存地址是:%#x\n",&a);
printf("互换前,b的内存地址是:%#x\n\n",&b);
change(&a,&b);//将a和b的地址传过去
printf("互换后,a是:%d\n",a);
printf("互换后,b是:%d\n\n",b);
system("pause");
}
结果如下:
两值成功互换,所以由此可见,单纯的传值是无法改变值的,只有传地址,才可以真正的改变值。
最后总结几点:
- 指针就是内存地址,内存地址就是指针
- &i,指取变量i的地址
- p=&i,指变量i的地址赋给p
- *p,指取值,把p对应的内存地址的值取出来
以上便是本人学习的小小总结,若有不对,请留言指出,谢谢~