高等教育出版社第8单元指针作者:林厚从信息学奥赛课课通(C++)高等教育出版社信息学奥赛课课通(C++)第1课指针的概念学习目标1.理解指针的概念。2.学会定义和使用指针。高等教育出版社信息学奥赛课课通(C++)指针指针是C++语言的一个重要概念,也是C++语言的重要特色。C++语言的高度灵活性及极强的表达能力,在很大程度上表现在巧妙而灵活的运用指针。通过指针可以有效地表示复杂的数据结构;能够方便地处理数组和字符串;能够动态地分配内存,直接对内存地址进行操作;利用指针作为函数参数,能够实现“一次函数调用,有多个返回值”的目的。因此,必须深入学习和理解指针的概念,体会和掌握指针的各种操作,熟练应用指针去实践编程。高等教育出版社信息学奥赛课课通(C++)1.指针的概念对于“inta=3;”,系统会在内存的某个区域开辟连续4个字节的单元存储。对a的操作就是对该内存区域进行操作,至于是具体的哪4个单元,我们并不关心。内存单元的位置(编号)叫作“地址”,可以通过取地址操作符“&”获得一个变量a的起始地址(首个存储单元的地址):&a。指针也是一个变量。和普通变量不同的是,指针变量里存储的数据是一个内存地址,就好像一个指示器,指引着你去该内存地址开始的一块内存区域存取数据。高等教育出版社信息学奥赛课课通(C++)2.指针的定义和使用指针变量的定义格式为:数据类型*指针变量;可以通过赋值语句给指针变量赋值,例如“p=&a;”表示把变量a的内存地址赋值给p,如图8.1-1所示。指针变量初始化:int*p=NULL;高等教育出版社信息学奥赛课课通(C++)例1、数字变化【问题描述】输入两个不同的整数,把较小的那个数翻倍并输出。【输入格式】一行两个整数(int范围以内),之间用一个空格隔开。【输出格式】一行一个整数,较小数翻倍后的结果。【输入样例】23【输出样例】4高等教育出版社信息学奥赛课课通(C++)//p8-1-1#includeiostreamusingnamespacestd;intmain(){inta,b;int*p;cinab;if(ab)p=&a;elsep=&b;cout*p*2endl;//取出p指向的内存单元里的整数,乘以2输出return0;}高等教育出版社信息学奥赛课课通(C++)【程序说明】1)变量a和b一旦定义,系统就会给它们分配内存空间,而且在程序运行过程中,其内存地址是固定不变的,这种存储方式称为“静态存储”。2)指针变量p定义后,其地址空间是不确定的,默认是NULL。当执行到p=&a或者p=&b时,p才指向a或者b的地址,才能确定p的值。这种储存方式称为“动态存储”。3)指针的动态性,还体现在可以根据需要,通过函数new()随时申请。看以下例2:高等教育出版社信息学奥赛课课通(C++)例2、阅读程序,写出程序的运行结果。//p8-1-2#includeiostreamusingnamespacestd;intmain(){int*p;char*q;p=new(int);q=new(char);*p=65;*q=*p;cout*p““*qendl;return0;}高等教育出版社信息学奥赛课课通(C++)【程序说明】1)运行程序,输出结果为“65A”。2)程序中声明了两个指针类型:一个指向整数类型的指针p和一个指向字符类型的指针q,分别通过new(int)和new(char)为p和q向内存申请空间。3)“*p=65;”把65这个整数存放到p所指向的内存单元。4)“*q=*p;”把p所指向的内存单元里的值赋值给q所指向的内存单元,由于q指向的是一个字符类型,而p指向的是一个整数类型,在赋值的时候执行了类型的强制转换,最终q所指向的内存单元里存储的是65号字符即为A。高等教育出版社信息学奥赛课课通(C++)3.指针的理解高等教育出版社信息学奥赛课课通(C++)(1)指针的类型从语法角度看,把指针定义语句里的指针名字去掉,剩下的部分就是这个指针的类型,也就是指针本身所具有的类型。int*ptr;//指针的类型是int*char*ptr;//指针的类型是char*int**ptr;//指针的类型是int**int(*ptr)[3];//指针的类型是int(*)[3]int*(*ptr)[4];//指针的类型是int*(*)[4]高等教育出版社信息学奥赛课课通(C++)(2)指针所指向的类型当通过指针来访问指针所指向的内存区域时,指针所指向的类型决定了编译器将把那片内存区域里的内容当作什么来看待。从语法上看,把指针定义语句中的指针名字和名字左边的指针声明符“*”去掉,剩下的就是指针所指向的类型。int*ptr;//指针所指向的类型是intchar*ptr;//指针所指向的类型是charint**ptr;//指针所指向的类型是int*int(*ptr)[3];//指针所指向的类型是int()[3]int*(*ptr)[4];//指针所指向的类型是int*()[4]在指针的算术运算中,指针所指向的类型有很大的作用。指针的类型和指针所指向的类型是两个不同的概念。高等教育出版社信息学奥赛课课通(C++)(3)指针的值指针的值是指针本身存储的数值,这个值将被编译器当作一个地址,而不是一般的数值。在位长32位的系统中,内存地址都是32位的,所以所有类型的指针的值都是一个32位整数。指针所指向的内存区域就是从指针的值所代表的那个内存地址开始,长度为sizeof(指针所指向的类型)的一片内存区域。我们说一个指针的值是X,就相当于说该指针指向了以X为首地址的一片内存区域。指针所指向的内存区域和指针所指向的类型是两个完全不同的概念。高等教育出版社信息学奥赛课课通(C++)(4)指针本身所占据的内存区用函数sizeof(指针的类型)测一下就知道了。在32位的系统中,指针本身占据了4字节的长度。高等教育出版社信息学奥赛课课通(C++)例3、阅读程序,写出程序的运行结果。//p8-1-3#includebits/stdc++.husingnamespacestd;intmain(){int*p,*q;p=(int*)malloc(40);//动态申请40字节用来存放int类型,并返回首地址给pq=p;*p=1;p++;*p=2;free(q);//释放刚才申请的40字节的空间return0;}高等教育出版社信息学奥赛课课通(C++)【程序说明】(1)单步跟踪程序,发现执行完“*p=1;”,q和p为同一个地址,*p和*q的值也都是1。(2)继续跟踪程序,执行完“*p=2;”,p指向了下一个整数空间,在原来的地址上加4,因为一个整型占4个字节。*p的值也变成了2。(3)程序中的“free(q);”是释放一开始申请的40个字节的内存空间,是配合malloc()使用。注意释放的是内存,q和p的地址还在,指针并没有被释放,指针仍然指向原来的存储空间。指针是一个变量,只有程序结束时才被销毁。释放了内存空间后,原来指向这块空间的指针还是存在,只不过现在指针指向的内容是未定义的,里面可能会有一些垃圾内容。继续跟踪看看p、q、*p、*q的值。高等教育出版社信息学奥赛课课通(C++)动态申请内存(1)malloc()void*malloc(unsignedsize);在内存的动态存储区中分配一块长度为size字节的连续区域,参数size为需要内存空间的长度,返回该区域的首地址。(2)calloc()void*calloc(size_tnumelements,size_tsizeofelement);与malloc相似,参数sizeofelement为申请地址的单位元素长度,numelements为元素个数,即在内存中申请numelements*sizeofelement字节大小的连续地址空间。(3)realloc()void*realloc(void*ptr,unsignednewsize);给一个已经分配了地址的指针重新分配空间,参数ptr为原有的空间地址,newsize是重新申请的地址长度。高等教育出版社信息学奥赛课课通(C++)实践巩固高等教育出版社信息学奥赛课课通(C++)第2课指针的引用与运算学习目标1.理解并学会引用指针。2.掌握指针的常用运算。高等教育出版社信息学奥赛课课通(C++)1.指针的引用首先理解指针变量与普通变量的区别和对应关系。例如,定义一个指针变量“int*p;”和一个普通变量“inta;”,关于两者之间的各种引用方式对应关系如下:1)“p”等同于“&a”,表示的是内存地址。2)“*p”等同于“a”,表示变量里存储的实际数据。3)“*p=3;”等同于“a=3;”,表示变量的赋值方法。高等教育出版社信息学奥赛课课通(C++)2.指针的运算如果定义的是局部指针变量,其地址就是随机的,直接操作会引发不可预测的错误。所以,指针变量一定要初始化后才能引用。由于指针变量存储的是内存地址,所以也可以执行加法、减法运算,一般用来配合数组进行寻址操作。例如:高等教育出版社信息学奥赛课课通(C++)例1、阅读并上机调试以下程序,体会指针变量的加法运算。//p8-2-1#includeiostreamusingnamespacestd;intmain(){inta[100],n;cinn;for(inti=0;in;i++)cina[i];int*p=&a[0];//指针p指向数组首元素的地址for(inti=0;in;i++){cout*pendl;p++;//指针每次往后移动一个区域}return0;}高等教育出版社信息学奥赛课课通(C++)【问题分析】1)程序的作用是输入n及n个整数,使用指针变量依次遍历输出。2)程序中的“p++”是广义的“p=p+1”,本质上是“p+sizeof(int)”。3)注意,“*p+3”和“*(p+3)”是不同的。对于本题,前者是指a[0]+3,而后者是指a[3]。高等教育出版社信息学奥赛课课通(C++)例2、求和【问题描述】输入n个正整数,要求对这n个数中的奇数和偶数分别求和。【输入格式】第1行1个正整数n,1≤n≤5000。以下n行,每行一个正整数(1~20000之间)。【输出格式】2行2个整数。第1行为所有奇数之和,第2行为所有偶数之和。【输入样例】5310758【输出样例】1518高等教育出版社信息学奥赛课课通(C++)//p8-2-2#includeiostreamusingnamespacestd;intmain(){intn,a[5011];int*p,*s1,*s2;//s1和s2指向的单元分别存放偶数和、奇数和cinn;for(inti=0;in;i++)cina[i];p=&a[0];s1=new(int);//申请一个存放整数类型的内存空间,把地址记录在s1中*s1=0;//累加器赋初值0s2=new(int);//申请一个存放整数类型的内存空间,把地址记录在s2中*s2=0;//累加器赋初值0for(inti=0;in;i++){if(*p%2==0)*s1+=*p;else*s2+=*p;p++;}cout*s2endl*s1endl;return0;}高等教育出版社信息学奥赛课课通(C++)例3、阅读并上机调试以下程序,体会无类型指针的使用。//p8-2-3#includeiostreamusingnamespacestd;intmain(){inta=10;doubleb=3.5;void*p;p=&a;cout*(int*)pendl;p=&b;cout*(double*)pendl;return0;}高等教育出版社信息学奥赛课课通(C++)例4、阅读并上机调试以下程序,体会多重指针的使用。//p8-2-4#includeiostreamusingnamespacestd;intmain(){inta=10;int*p;int**pp;p=&a;pp=&