一.*p,**p
1.一级指针
以下图表示的意思是:
a的地址为0XA0,定义一个指针p,指向a的地址,计算机也会给p一个内存空间&p:0XB0
图中:p=0XA0,&p=0XB0,*p=3
来看代码:
#include<stdio.h> void test(int *p1){ *p1=114514; } int main() { int *p1=NULL; int p=2333; p1=&p; printf("*p1=%d,p1=%d,&p1=%d,&(*p1)=%d,\np=%d,&p=%d\n",*p1,p1,&p1,&(*p1),p,&p); test(p1); printf("*p1=%d,p1=%d,&p1=%d,&(*p1)=%d,\np=%d,&p=%d\n",*p1,p1,&p1,&(*p1),p,&p); getchar(); return 0; }
得到的结果一个一个看:
*p1=p这个变量的值
p1=p的内存地址,即(p1=&p)
&p1=计算机给p1的内存地址
&(*p1)=(*p1)这个变量的内容的地址,所以我们得到&(*p1)=&p=p1,多画图理解下就不难了。
2.二级指针(**p)
按照之前一级指针的说法,*p存放的是一级指针的地址,**p存放的就是*p的地址
以此类推***p存放的就是比他第一级指针的地址:用图理解下:
&p1=0xc0(计算机给p1分配的地址)
p1=&p=0xb0(一级指针自身的地址)
*p1=0xa0(相当于对p1所指向的地址(0xb0)进行解析,我们找到(0xb0),发现他代表的是p的地址,而p指针所指向的是地址是(0xa0) )
注意区别:p1本身的地址和p1所指向的地址
**p1=3(同理,继续解析,得到变量a的值为3),不难发现:**p1=*p
来看代码:
#include<stdio.h> void test2(int **p){ printf("**p2=%d,&(*p2)=%d,*p2=%d,p2=%d,&p2=%d\n",**p,&(*p),*p,p,&p); } int main(){ int *p1=NULL; int p=114514; p1=&p; printf("*p1=%d,p1=%d,&p1=%d,&(*p1)=%d\n",*p1,p1,&p1,&(*p1)); test2(&p1); getchar(); return 0; }
结果:
其中p2代表二级指针,p1代表一级指针
●p2=&p1(p2=p1的地址)
●*p2=p1
●**p2=*p1
我们可以看到p2对p1的逐步解析(从p1的地址>到p1所指的地址>p1所指的地址的内容)
●&p2代表计算机给p2分配的地址
●&(*p2)=p2=&p1
指针确实较难理解,学习时多画图多分析
再看两段代码
#include<stdio.h> int main() { char *p="abcdf";//"abcdf"是一个常量字符串 printf("%c\n",*p);//输出a,a是字符串的首地址 //printf("%s\n",*p);//错误,*p是一个"char"类型的变量 printf("%s",p);//输出指针p所指向的字符串的值,即"abcdf" return 0; } #include<stdio.h> int main() { char *a="abcdef"; char *p=a; char **pp=&p; printf("%s\n",p);//输出abcdef ,输出指针p所指向的字符串"abcdef" printf("%c",**pp); //输出a ,**pp=&p,**p指向p的地址,*pp指向的就是指针p的值,其第一个字符是'a' return 0; }
可以自己多写代码分析结果
二.指针的引用
来看一段代码
#include<stdio.h> int main() { int a=100,b=10; int *pointer_1,*pointer_2; pointer_1=&a; pointer_2=&b; printf("a=%d,b=%d\n",a,b); printf("*pointer_1=%d,*pointer_2=%d",*pointer_1,*pointer_2); return 0; }
结果
a=100,b=10
*pointer_1=100,*pointer_2=10
第四行的*pointer_1,*pointer_2,表示定义两个指针变量pointer_1和pointer_2
而printf函数中的*pointer_1,*pointer_2则代表指针变量pointer_1和pointer_2所指向的变量
指针变量中只能存放地址,不能将一个整数赋给一个指针变量
*pointer_1=100;//pointer_1是指针变量,100是整数,不合法
从形式上看100是整常数,而整常数只能赋给整型变量,而不能赋给指针变量
那么应该如何正确引用指针呢?
1.给指针变量赋值
p=&a;//指针变量p的值是变量a的地址,p指向a
2.引用指针变量指向的变量
printf(“%d”,*p); //以整数形式输出指针变量p所指向的变量的值,即变量a的值
如果有以下赋值语句:
*p=1,那么相当于把1赋值给a,a=1;//注意与上面区别,这是在p=&a的前提下
3.引用指针变量的值
printf("%o",p); //以8进制形式输出指针变量p的值,如果p指向了a,就是输出a的地址(&a)
举个例子,来看以下代码
#include<stdio.h> int main() { int *p1,*p2,*p,a,b; printf("输入两个整数:"); scanf("%d,%d",&a,&b); p1=&a; p2=&b; if(a<b) { p=p1; p1=p2; p2=p; } printf("a=%d,b=%d\n",a,b); printf("max=%d,min=%d\n",*p1,*p2); return 0; }
结果
输入两个整数:5,9
a=5,b=9
max=9,min=5
注:a和b的值并未交换,他们仍保持原值,但是p1和p2的值改变了
修改这段代码
•可以直接对p1和p2赋以新值,不必定义中间变量p
p1=&b,p2=&a;
•定义一个swap函数,实现交换两个变量的值
void swap(int *p1,int *p2) { int temp; temp=*p1; *p1=*p2; *p2=temp; }
在函数调用时,将实参变量(pointer_1,pointer_2)的值传送给形参变量,所以p1的值为&a,p2的值为&b,接着执行swap函数的函数体,使*p1,*p2的值互换,也就是a,b值互换,函数调用后,形参p1,p2释放(如图所示)
所以完整代码
#include<stdio.h> void swap(int *p1,int *p2) { int temp; temp=*p1; *p1=*p2; *p2=temp; } int main() { int a,b; int *pointer_1,*pointer_2; printf("输入两个整数:"); scanf("%d,%d",&a,&b); pointer_1=&a; pointer_2=&b; if(a<b) swap(pointer_1,pointer_2); printf("max=%d,min=%d\n",a,b); return 0; }
注意不能这样写
void swap(int *p1,int *p2) { int *temp; *temp=*p1; *p1=*p2; *p2=*temp; }
*temp是指针变量temp所指向的变量,但是没有给temp赋值,所以*temp指向未知的存储单元,而这个未知的存储单元中可能存储着一个有用的数据,这样就可能破坏系统正常工作状况。
如果这样写
void swap(int x,int y) { int temp; temp=x; x=y; y=temp; }
那么调用后是这样的结果
x,y的值互换了,但并未影响到a,b的值,所以x,y释放后,a,b并未交换,所以应该使用指针变量作为函数参数,在函数执行过程中,指针变量所指向的变量值发生变化,函数调用后,这些变量值的变化依然保留
注:不能通过改变形参的值而使指针实参的值改变
#include<stdio.h> void swap(int *p1,int *p2) { int *p; p=p1; p1=p2; p2=p; } int main() { int a,b; int *pointer_1,*pointer_2; printf("输入两个整数:"); scanf("%d,%d",&a,&b); pointer_1=&a; pointer_2=&b; if(a<b) swap(pointer_1,pointer_2); printf("max=%d,min=%d\n",a,b); return 0; }
第(d)步是不能完成的,不可能通过执行调用函数来改变实参指针变量的值