1、第8章善于利用指针8.1指针是什么8.2指针变量8.3通过指针引用数组8.4通过指针引用字符串8.58.6返回指针值的函数8.7指针数组和多重指针8.8动态内存分配与指向它的指针变量8.9有关指针的小结指向函数的指针18.1指針是什么例如:VC+为整型变量分配4个字节,对单精度浮点型变量分配个字节,对字符型变量如果在程序中定义了一个变量,在对程序进行编译时,系统就会给分配个字节。该变量分配内存单元。编译系统根据程序中定义的变量类型,分配一定长度的空间,内存区的每一个字节有一个编号,这就是“地址”,它相当于旅馆中的房间号。在地址所标识的内存单元中存放数据,这相当于旅馆房间中居住的旅客一样。由于通
2、过地址能找到所需的变量单元,我们可以说,地址指向该变量单元。将地址形象化地称为“指针”。务必弄清楚存储单元的地址和存储单元的内容这两个概念的区别2inti=3,j=6,k;printf(“%d”,i);通过变量名i找到i的地址2000,从而从存储单元读取33inti=3,j=6,k;k=i+j;从这里取3从这里取6将9送到这里直接存取4inti=3,j=6,k;定义特殊变量i_pointeri_pointer=&i;50*i_pointer=50;将i的地址存到这里间接存取5i直接存取32000i_pointer*i_pointer间接存取2000320006为了表示将数值送到变量中,可以有两
3、种表达方法:(1)将3直接送到变量i所标识的单元中,例如:i=3;(2)将3送到变量i_pointer所指向的单元(即变量i的存储单元),例如:*i_pointer=3;其中*i_pointer表示i_pointer指向的对象指向就是通过地址来体现的,假设i_pointer中的值是变量的地址(2000),这样就在i_pointer和变量之间建立起一种联系,即通过i_pointer能知道i的地址,从而找到变量i的内存单元由于通过地址能找到所需的变量单元,因此说,地址指向该变量单元。将地址形象化地称为“指针”。意思是通过它能找到以它为地址的内存单元7一个变量的地址称为该变量的“指针”例如,地址20
4、00是变量的指针如果有一个变量专门用来存放另一变量的地址(即指针),则它称为“指针变量”i_pointer就是一个指针变量。指针变量就是地址变量,用来存放地址的变量,指針变量的值是地址(即指针)“指针”和“指针变量”是不同的概念可以说变量i的指针是2000,而不能说i的指针变量是2000指针是一个地址,而指针变量是存放地址的变量88.2指针变量8.2.1使用指针变量的例子8.2.2怎样定义指针变量8.2.3怎样引用指针变量8.2.4指针变量作为函数参数98.2.1使用指针变量的例子例8.1通过指针变量访问整型变量。解题思路:先定义2个整型变量,再定义2个指针变量,分别指向这两个整型变量,通过访
5、问指针变量,可以找到它们所指向的变量,从而得到这些变量的值。10#includeintmain()inta=100,b=10;定义两个指针变量int*pointer_1,*pointer_2;pointer_1=&a;直接输出变量a和b的值pointer_2=&b;printf(“a=%d,b=%dn”,a,b);printf(“*pointer_1=%d,*pointer_2=使使pointer_1pointer_2指向指向ab%dn”,*pointer_1,*pointer_2);return0;间接输出变量a和b的值11#includeintmain()inta=100,b=10;此处*
6、与类型名在一起。此时共同定义指针变量int*pointer_1,*pointer_2;pointer_1=&a;pointer_2=&b;printf(“a=%d,b=%dn”,a,b);printf(“*pointer_1=%d,*pointer_2=%dn”,*pointer_1,*pointer_2);return0;此处*与指针变量一起使用。此时代表指针变量所指向的变量128.2.2怎样定义指针变量定义指针变量的一般形式为:类型*指针变量名;如:int*pointer_1,*pointer_2;int是为指针变量指定的“基类型”,基类型指定指针变量可指向的变量类型如pointer_1可
7、以指向整型变量,但不能指向浮点型变量138.2.2怎样定义指针变量下面都是合法的定义和初始化:float*pointer_3;char*pointer_4;inta,b;int*pointer_1=&a,*pointer_2=&b;pointer_3pointer_3pointer_1*pointer_12000;&a;&a;&a;错误正确错误错误148.2.3怎样引用指针变量使p指向a在引用指针变量时,可能有三种情况:给指针变量赋值。如:*p相当于ap=&a;引用指针变量指向的变量。如有p=&a;*p=1;则执行printf(“%d”,*p);将输出1引用指针变量的值。如:printf(“%
8、o”,p);以八进制输出a的地址158.2.3怎样引用指针变量要熟练掌握两个有关的运算符:(1)取地址运算符。&a是变量a的地址(2)*指针运算符(“间接访问”运算符)如果:p指向变量a,则*p就代表a。k=*p;(把a的值赋给k)*p=1;(把1赋给a)16例8.2输入a和b两个整数,按先大后小的顺序输出a和b。解题思路:用指针方法来处理这个问题。不交换整型变量的值,而是交换两个指针变量的值。17p1ap&a5#includeintmain()int*p1,*p2,*p,a,b;&b9printf(“integernumbers:);scanf(“%d,%d”,&a,&b);p1=&a;p2
9、b;if(ab)成立p=p1;p1=p2;p2=p;printf(“a=%d,b=%dn”,a,b);printf(“%d,%dn”,*p1,*p2);return0;p2b18p1ap&b&a5#includeintmain()int*p1,*p2,*p,a,b;&a&b9printf(“integernumbers:);scanf(“%d,%d”,&a,&b);p1=&a;p2=&b;if(ab)p=p1;p1=p2;p2=p;printf(“a=%d,b=%dn”,a,b);printf(“%d,%dn”,*p1,*p2);return0;p2b19p1ap&b&a5#include
10、intmain()int*p1,*p2,*p,a,b;&a&b9printf(“integernumbers:);scanf(“%d,%d”,&a,&b);p1=&a;p2=&b;if(ab)p=p1;p1=p2;p2=p;printf(“a=%d,b=%dn”,a,b);printf(“%d,%dn”,*p1,*p2);return0;p2b20p1ap&b&a5#includeintmain()int*p1,*p2,*p,a,b;&a&b9printf(“integernumbers:);scanf(“%d,%d”,&a,&b);p1=&a;p2=&b;if(ab)p=p1;p1=p2;p
11、2=p;printf(“a=%d,b=%dn”,a,b);printf(“%d,%dn”,*p1,*p2);return0;p2b可否改为p1=&b;p2=&a;?21注意:a和b的值并未交换,它们仍保持原值但p1和p2的值改变了。p1的值原为&a,后来变成&b,p2原值为&b,后来变成&a这样在输出*p1和*p2时,实际上是输出变量b和a的值,所以先输出9,然后输出5228.2.4指针变量作为函数参数例8.3题目要求同例8.2,即对输入的两个整数按大小顺序输出。现用函数处理,而且用指针类型的数据作函数参数。解题思路:定义一个函数swap,将指向两个整型变量的指针变量作为实参传递给swap函数
12、的形参指针变量,在函数中通过指针实现交换两个变量的值。23#includeintmain()voidswap(int*p1,int*p2);inta,b;int*pointer_1,*pointer_2;printf(pleaseenteraandb:);scanf(“%d,%d”,&a,&b);pointer_1=&a;pointer_1pointer_2=&b;if(ab)swap(pointer_1,pointer_2);printf(“max=%d,min=%dn”,a,b);return0;apointer_2b&a5&b924voidswap(int*p1,int*p2)intte
13、mp;temp=*p1;*p1=*p2;*p2=temp;pointer_1apointer_2b&a95&b59p1&ap2&b25voidswap(int*p1,int*p2)inttemp;temp=*p1;*p1=*p2;*p2=temp;voidswap(int*p1,int*p2)int*temp;错!*temp=*p1;*p1=*p2;*p2=*temp;无确定的指向26#includeintmain()错!无法交换a,bif(ab)swap(a,b);printf(“max=%d,min=%dn”,a,b);return0;ab59voidswap(intx,inty)intt
14、emp;59x95ytemp=x;x=y;y=temp;27如果想通过函数调用得到个要改变的值:在主调函数中设个变量,用个指针变量指向它们设计一个函数,有n个指针形参。在这个函数中改变这个形参的值在主调函数中调用这个函数,在调用时将这n个指针变在执行该函数的过程中,通过形参指针变量,改变它主调函数中就可以使用这些改变了值的变量288.3通过指针引用数组8.3.1数组元素的指针8.3.2在引用数组元素时指针的运算8.3.3通过指针引用数组元素8.3.4用数组名作函数参数8.3.5通过指针引用多维数组298.3.1数组元素的指针一个变量有地址,一个数组包含若干元素,每个数组元素都有相应的地址指针变
15、量可以指向数组元素(把某一元素的地址放到一个指针变量中)所谓数组元素的指针就是数组元素的地址30可以用一个指针变量指向一个数组元素inta10=1,3,5,7,9,11,13,15,17,19;int*p;p=&a0;注意:等价于数组名p=a;a不代表整个数组,只代表数组首元素的地址。等价于int*p=a;“p=a;”的作用是“把或int*p=&a0;a数组的首元素的地址赋给指针变量p”,而不是“把数组a各元素的值赋给p”。318.3.2在引用数组元素时指针的运算在指针指向数组元素时,允许以下运算:加一个整数(用+或+=),如p+1减一个整数(用-或-=),如p-1自加运算,如p+,+p自减运
16、算,如p-,-p两个指针相减,如p1-p2(只有p1和p2都指向同一数组中的元素时才有意义)32(1)如果指针变量p已指向数组中的一个元素,则p+1指向同一数组中的下一个元素,p-1指向同一数组中的上一个元素。floata10,*p=a;假设a0的地址为2000,则p的值为2000p+1的值为2004P-1的值为1996越界33pp+1,a+1a0a1a2a3a4a5a6a7a8a9(2)如果的初值为&a0,则p+i和a+i就是数组元素ai的地址,或者说,它们指向a数组序号为i的元素p+i,a+ip+9,a+934pp+1,a+1a0a1a2a3a4a5a6a7a8a9(3)*(p+i)或*(
17、a+i)是p+i或a+i所指向的数组元素,即ai。p+i,a+i*(p+i)p+9,a+935a0a1a2a3a4a5a6a7a8a9(4)如果指针p1和p2都指向同一数组p1p2-p1的值是4p2不能p1+p2368.3.3通过指针引用数组元素引用一个数组元素,可用下面两种方法:()下标法,如ai形式()指针法,如*(a+i)或*(p+i)其中a是数组名,p是指向数组元素的指针变量,其初值p=a378.3.3通过指针引用数组元素例8.6有一个整型数组a,有10个元素,要求输出数组中的全部元素。解题思路:引用数组中各元素的值有3种方法:(1)下标法;(2)通过数组名计算数组元素地址,找出元素的
18、值;(3)用指针变量指向数组元素分别写出程序,以资比较分析。38(1)下标法。#includeintmain()inta10;inti;printf(“enter10integernumbers:n);for(i=0;i10;i+)scanf(%d,&ai);for(i=0;i10;i+)printf(“%d”,ai);printf(%return0;n);39(2)通过数组名计算数组元素地址,找出元素的值#includeintmain()inta10;inti;printf(“enter10integernumbers:n);for(i=0;i10;i+)scanf(%d,&ai);for(
19、i=0;i10;i+)printf(“%d”,*(a+i);printf(n);return0;scanf(%d,a+i);40(3)用指针变量指向数组元素#includeintmain()inta10;int*p,i;printf(“enter10integernumbers:n);for(i=0;i10;i+)scanf(%d,&ai);for(p=a;p(a+10);p+)printf(“%d”,*p);printf(n);return0;for(p=a;p(a+10);p+)for(p=scanfa;p(a+10);(%d,pa);+)printf(“%d”,*a);错!413种方法的
20、比较:第(1)和第(2)种方法执行效率相同编译系统是将ai转换为*(a+i)处理的,即先计算元素地址。因此用第(1)和第(2)种方法找数组元素费时较多。第(3)种方法比第(1)、第(2)种方法快用指针变量直接指向元素,不必每次都重新计算地址,像p+这样的自加操作是比较快的这种有规律地改变地址值(p+)能大大提高执行效率用下标法比较直观,能直接知道是第几个元素。用地址法或指针变量的方法不直观,难以很快地判断出当前处理的是哪一个元素。42例8.7通过指针变量输出整型数组a的10个元素。解题思路:用指针变量p指向数组元素,通过改变指针变量的值,使p先后指向a0到a9各元素。43#includeint
21、main()int*p,i,a10;重新执行p=a;printf(“enter10integernumbers:n);for(i=0;i10;i+)scanf(“%d”,p+);for(i=0;i10;i+,p+)p=a;printf(“%d”,*p);退出循环时p指向a9后面的存储单元printf(n);return0;因此执行此循环出问题44*(p+)是先取*p的值,然后使p加1;*(+p)是先使p加1,再取*p*p+*(p+)*(p+)与*(+p)+(*p)P指向当前a数组中的第i个元素ai*(p-)ai-*(+p)a+i*(-p)a-i458.3.4用数组名作函数参数用数组名作函数参数
22、时,因为实参数组名代表该数组首元素的地址,形参应该是一个指针变量C编译都是将形参数组名作为指针变量来处理的46intmain()voidfun(intarr,intn;intarray10;fun(array,10);return0;fun(int*arr,intn)voidfun(intarr,intn)47arrarray0intmain()voidfun(intarr,intn;arr0intarray10;array3arr+3arr3fun(array,10);return0;voidfun(int*arr,intn)array数组48实参数组名是指针常量,但形参数组名是按指针变量处
23、理在函数调用进行虚实结合后,它的值就是实参数组首元素的地址在函数执行期间,形参数组可以再被赋值voidfun(arr,intn)printf(%dn,*arr);arr=arr+3;printf(%dn,*arr);49例8.8将数组a中n个整数按相反顺序存放解题思路:将a0与an-1对换,将a4与a5对换。ij50例8.8将数组a中n个整数按相反顺序存放解题思路:将a0与an-1对换,将a4与a5对换。ij51#includeintmain()voidinv(intx,intn);inti,a10=3,7,9,11,0,6,7,5,4,2;for(i=0;i10;i+)printf(“%d”
24、ai);printf(n);inv(a,10);for(i=0;i10;i+)printf(“%d”,ai);printf(n);return0;52voidinv(intx,intn)inttemp,i,j,m=(n-1)/2;for(i=0;i=m;i+)j=n-1-i;temp=xi;xi=xj;xj=temp;voidinv(intx,intn)inttemp,*i,*j;i=x;j=x+n-1;for(;ij;i+,j-)temp=*i;*i=*j;*j=temp;优化53例8.9改写例8.8,用指针变量作实参。#includeintmain()voidinv(int*x,intn
25、);不可少!inti,arr10,*p=arr;for(i=0;i10;i+,p+)scanf(“%inv(p,10);for(p=arr;parr+10;p+)d”,p);printf(“%d”,*p);printf(n);return0;548.3.5通过指针引用多维数组指针变量可以指向一维数组中的元素,也可以指向多维数组中的元素。但在概念上和使用方法上,多维数组的指针比一维数组的指针要复杂一些。558.3.5通过指针引用多维数组1.多维数组元素的地址inta34=1,3,5,7,9,11,13,15,17,19,21,23;a0a0+1a0+2a0+3aa+1a+2列指针a0a1a219
26、35711191321152317行指针56行指针每加1,走一行a代表第0行首地址a+1代表第1行首地址a+2代表第2行首地址a0a0+1a0+2a0+3aa+1a+2列指针a0a1a21935711191321152317行指针57a+i代表行号为i的行首地址(按行变化)*(a+i)代表什么?相当于aia0a0+1a0+2a0+3aa+1a+2列指针a0a1a21935711191321152317行指针58列指针每加1,走一列a0代表a00的地址a0+1代表a01的地址a0+2代表a02的地址a0+3代表a03的地址a0a0+1a0+2a0+3aa+1a+2列指针a0a1a21935711
27、191321152317行指针59a1代表谁的地址?a1+1代表谁的地址?a1+2代表谁的地址?a1+3代表谁的地址?a0a0+1a0+2a0+3aa+1a+2列指针a0a1a21935711191321152317行指针60ai+j代表谁的地址?代表aij的地址*(ai+j)代表什么?代表元素aij*(*(a+i)+j)代表什么?与*(ai+j)等价a0a0+1a0+2a0+3aa+1a+2列指针a0a1a21935711191321152317行指针61例8.11二维数组的有关数据(地址和值)#includeintmain()inta34=1,3,5,7,9,11,13,15,17,19,
28、21,23;62printf(“%d,%dn”,a,*a);printf(“%d,%dn”,a0,*(a+0);printf(“%d,%dn”,&a0,&a00);printf(“%d,%dn”,a1,a+1);printf(“%d,%dn”,&a10,*(a+1)+0);printf(“%d,%dn”,a2,*(a+2);printf(“%d,%dn”,&a2,a+2);printf(“%d,%dn”,a10,*(*(a+1)+0);printf(“%d,%dn”,*a2,*(*(a+2)+0);return0;63printf(“%d,%dn”,a,*a);printf(“%d,%dn”,
29、a0,*(a+0);printf(“%d,%dn”,&a0,&a00);printf(“%d,%dn”,a1,a+1);printf(“%d,%dn”,&a10,*(a+1)+0);printf(“%d,%dn”,a2,*(a+2);printf(“%d,%dn”,&a2,a+2);printf(“%d,%dn”,a10,*(*(a+1)+0);printf(“%d,%dn”,*a2,*(*(a+2)+0);return0;64printf(“%d,%dn”,a,*a);printf(“%d,%dn”,a0,*(a+0);printf(“%d,%dn”,&a0,&a00);printf(“%d
30、dn”,a1,a+1);printf(“%d,%dn”,&a10,*(a+1)+0);printf(“%d,%dn”,a2,*(a+2);printf(“%d,%dn”,&a2,a+2);printf(“%d,%dn”,a10,*(*(a+1)+0);printf(“%d,%dn”,*a2,*(*(a+2)+0);return0;652.指向多维数组元素的指针变量(1)指向数组元素的指针变量例8.12有一个34的二维数组,要求用指向元素的指针变量输出二维数组各元素的值。66解题思路:二维数组的元素是整型的,它相当于整型变量,可以用int*型指针变量指向它二维数组的元素在内存中是按行顺序存放
31、的,即存放完序号为0的行中的全部元素后,接着存放序号为1的行中的全部元素,依此类推因此可以用一个指向整型元素的指针变量,依次指向各个元素67#includeintmain()逐个访问各元素时常用此类指针inta34=1,3,5,7,9,11,13,15,17,19,21,23;int*p;for(p=a0;pa0+12;p+)if(p-a0)%4=0)printf(“n”);printf(“%4d”,*p);printf(n);return0;控制换行68aij在数组中的相对位置的计算公式:i*m+j若开始时指针变量p指向a00,aij的地址为&a00+(i*m+j)或p+(i*m+j)C语言
32、规定数组下标从0开始,aij在数组中的相对位置的计算公式:(i-1)*m+(j-1)m1357n91113151719212369(2)指向由个元素组成的一维数组的指针变量例8.13输出二维数组任一行任一列元素的值。解题思路:假设仍然用例8.12程序中的二维数组,例8.12中定义的指针变量是指向变量或数组元素的,现在改用指向一维数组的指针变量。70#include行指针。不是int*型,而是intmain()inta34=1,3,5,7,9,11,13,15,数组的指针变量,有四个元素,int(*)4型,p被定义为指向一维因此p的基类型是一维数组17,19,21,23;int(*p)4,i,j
33、p=a;printf(“enterrowandcolum:);scanf(“%d,%d”,&i,&j);printf(“a%d,%d=%dn”,aiji,j,*(*(p+i)+j);return0;713.用指向数组的指针作函数参数一维数组名可以作为函数参数,多维数组名也可作函数参数。用指针变量作形参,以接受实参数组名传递来的地址。可以有两种方法:用指向变量的指针变量用指向一维数组的指针变量72例8.14有一个班,3个学生,各学4门课,计算总平均分数以及第n个学生的成绩。解题思路:这个题目是很简单的。本例用指向数组的指针作函数参数。用函数average求总平均成绩,用函数search找出并输
34、出第i个学生的成绩。73#includeintmain()voidaverage(float*p,intn);voidsearch(float(*p)4,intn);floatscore34=65,67,70,60,80,87,90,81,90,99,100,98;average(*score,12);search(score,2);return0;score00的地址74p65677060808790819099p+1voidaverage(float*p,intn)float*p_end;floatsum=0,aver;p_end=p+n-1;for(;p=p_end;p+)sum=sum
35、p);aver=sum/n;printf(average=%5.2fn,aver);100p_end9875#includeintmain()voidaverage(float*p,intn);voidsearch(float(*p)4,intn);floatscore34=65,67,70,60,80,87,90,81,90,99,100,98;average(*score,12);search(score,2);return0;二维数组首行地址76voidsearch(float(*p)4,intn)inti;printf(ThescoreofNo.%dare:n,n);for(i=
36、0;i4;i+)printf(%5.2f,*(*(p+n)+i);printf(n);p6580906787997090608198p+2100778.4通过指针引用字符串8.4.1字符串的引用方式8.4.2字符指针作函数参数8.4.3使用字符指针变量和字符数组的比较788.4.1字符串的引用方式字符串是存放在字符数组中的。引用一个字符串,可以用以下两种方法。(1)用字符数组存放一个字符串,可以通过数组名和格式声明“%s”输出该字符串,也可以通过数组名和下标引用字符串中一个字符。(2)用字符指针变量指向一个字符串常量,通过字符指针变量引用字符串常量。79例8.16定义一个字符数组,在其中存放字
37、符串“IloveChina!”,输出该字符串和第8个字符。解题思路:定义字符数组string,对它初始化,由于在初始化时字符的个数是确定的,因此可不必指定数组的长度。用数组名string和输出格式%s可以输出整个字符串。用数组名和下标可以引用任一数组元素。80#includeintmain()charstring=“IloveChina!”;stringstring+7printf(“%sn”,string);printf(“%cn”,string7);return0;81例8.17通过字符指针变量输出一个字符串。解题思路:可以不定义字符数组,只定义一个字符指针变量,用它指向字符串常量中的字符
38、通过字符指针变量输出该字符串。82#includeintmain()stringchar*string=“IloveChina!”;printf(“%sn”,string);return0;char*string;string=”IloveChina!”;string被定义为一个指针变量,基类型为字符型,只能指向一个字符型数据。string指向字符串的第一个字符。83#includeintmain()stringchar*string=“IloveChina!”;printf(“%sn”,string);string=”Iamastudent.”;printf(“%sn”,string);r
39、eturn0;84#includeintmain()char*string=“IloveChina!”;printf(“%sstringn”,string);string=”Iamastudent.”;printf(“%sn”,string);return0;85例8.18将字符串a复制为字符串b,然后输出字符串b。解题思路:定义两个字符数组a和b,用“Iamastudent.”对a数组初始化。将a数组中的字符逐个复制到b数组中。可以用不同的方法引用并输出字符数组元素,今用地址法算出各元素的值。86#includeintmain()chara=“Iamastudent.”,b20;检查ai是否
40、为0,ai是以*(a+i)表示的inti;for(i=0;*(a+i)!=0;i+)*(b+i)=*(a+i);*(b+i)=printf0;(stringbis:%sn“,b);printf(“stringais:%sn”,a);printf(stringbis:);for(i=0;bi!=0;i+)printf(“%c”,bi);printf(n);return0;878.4.2字符指针作函数参数如果想把一个字符串从一个函数“传递”到另一个函数,可以用地址传递的办法,即用字符数组名作参数,也可以用字符指针变量作参数。在被调用的函数中可以改变字符串的内容在主调函数中可以引用改变后的字符串。8
41、88.4.2字符指针作函数参数例8.20用函数调用实现字符串的复制。解题思路:定义一个函数copy_string用来实现字符串复制的功能,在主函数中调用此函数,函数的形参和实参可以分别用字符数组名或字符指针变量。分别编程,以供分析比较。89(1)用字符数组名作为函数参数#includeintmain()voidcopy_string(charfrom,charto);chara=Iamateacher.;charb=youareastudent.;printf(“a=%s将nb=%sa和b第一个字符的地址分别n,a,b);printf(copystringatostringb:n);copy_
42、string(a,b);printf(“a=%snb=%sn,a,b);return0;传给形参数组名from和to90voidcopy_string(charfrom,charto)inti=0;while(fromi!=0)toi=fromi;fromi和ai是同一个单元,toi和bi是同一个单元。i+;toi=0;91(2)用字符型指针变量作实参copy_string不变,在main函数中定义字符指针变量from和to,分别指向两个字符数组a,b。仅需要修改主函数代码92#includeintmain()voidcopy_string(charfrom,charto);chara=“Ia
43、mateacher.”;charb=“youareastudent.”;char*from=a,*to=b;printf(“a=%snb=%sn,a,b);printf(ncopystringatostringb:n);copy_string(from,to);printf(“a=%snb=%sn,a,b);return0;93(3)用字符指针变量作形参和实参#includeintmain()voidcopy_string(char*from,char*to);char*a=“Iamateacher.”;charb=“Youareastudent.”;char*p=b;printf(“a=%s
44、nb=%sn”,a,b);printf(ncopystringatostringb:n);copy_string(a,p);printf(“a=%snb=%sn”,a,b);return0;94voidcopy_string(char*from,char*to)for(;*from!=0;from+,to+)*to=*from;*to=0;958.4.3使用字符指针变量和字符数组的比较用字符数组和字符指针变量都能实现字符串的存储和运算,但它们二者之间是有区别的,不应混为一谈,主要有以下几点。(1)字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(字符串第1个字符的地
45、址),决不是将字符串放到字符指针变量中。968.4.3使用字符指针变量和字符数组的比较(2)赋值方式。可以对字符指针变量赋值,但不能对数组名赋值。char*a;a=”IloveChina!”;对charstr14;str0=I;对charstr14;str=”IloveChina!”;错(3)初始化的含义char*a=“IloveChina!”;与char*a;a=“IloveChina!”;等价charstr14=”IloveChina!”;与charstr14;str=”IloveChina!”;不等价978.4.3使用字符指针变量和字符数组的比较(4)存储单元的内容编译时为字符数组分配若
46、干存储单元,以存放各元素的值,而对字符指针变量,只分配一个存储单元char*a;scnaf(“%s”,a);错char*a,str10;a=str;scanf(“%s”,a);对988.4.3使用字符指针变量和字符数组的比较(5)指针变量的值是可以改变的,而数组名代表一个固定的值(数组首元素的地址),不能改变。例8.21改变指针变量的值。#include不能改为chara=“IloveChina!”;intmain()char*a=IloveChina!;a=a+7;printf(“%sn”,a);return0;998.4.3使用字符指针变量和字符数组的比较(6)字符数组中各元素的值是可以改
47、变的,但字符指针变量指向的字符串常量中的内容是不可以被取代的。chara=”House”,*b=”House”;a2=r;对b2=r;错?1008.4.3使用字符指针变量和字符数组的比较(7)引用数组元数对字符数组可以用下标法和地址法引用数组元素(a5,*(a+5)。如果字符指针变量p=a,则也可以用指针变量带下标的形式和地址法引用(p5,*(p+5))。char*a=IloveChina!;则a5的值是第6个字符,即字母e1018.4.3使用字符指针变量和字符数组的比较(8)用指针变量指向一个格式字符串,可以用它代替printf函数中的格式字符串。char*format;format=”a=
48、d,b=%fn”;printf(format,a,b);相当于printf(“a=%d,b=%fn”,a,b);1028.5指向函数的指针8.5.1什么是函数指针8.5.2用函数指针变量调用函数8.5.3怎样定义和使用指向函数的指针变量8.5.4用指向函数的指针作函数参数1038.5.1什么是函数指针如果在程序中定义了一个函数,在编译时,编译系统为函数代码分配一段存储空间,这段存储空间的起始地址,称为这个函数的指针。可以定义一个指向函数的指针变量,用来存放某一函数的起始地址,这就意味着此指针变量指向该函数。例如:int(*p)(int,int);定义p是指向函数的指针变量,它可以指向类型为整
49、型且有两个整型参数的函数。p的类型用int(*)(int,int)表示1048.5.2用函数指针变量调用函数例8.22用函数求整数a和b中的大者。解题思路:定义一个函数max,实现求两个整数中的大者。在主函数调用max函数,除了可以通过函数名调用外,还可以通过指向函数的指针变量来实现。分别编程并作比较。105(1)通过函数名调用函数#includeintmain()intmax(int,int);inta,b,c;printf(pleaseenteraandb:);scanf(%d,%d,&a,&b);c=max(a,b);printf(“%d,%d,max=%dn,a,b,c);return
50、0;106intmax(intx,inty)intz;if(xy)z=x;elsez=y;return(z);107(2)通过指针变量访问它所指向的函数#include值为整型且有两个intmain()intmax(int,int);只能指向函数返回整型参数的函数int(*p)(int,int);inta,b,c;p=max;printf(pleaseenteraandb:);p=max(a,b);错scanf(%d,%d,&a,&b);c=(*p)(a,b);printf(“%d,%d,max=%dn,a,b,c);return0;必须先指向,若写成1088.5.3怎样定义和使用指向函数的指






