《kj-第9章指针ppt课件(全).ppt》由会员分享,可在线阅读,更多相关《kj-第9章指针ppt课件(全).ppt(86页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第章第章 指针指针 本章概述 本章的学习目标主要内容1本章概述本章概述n指针是指针是C语言的特色之一,灵活运用指针可语言的特色之一,灵活运用指针可使程序更加高效、简洁。使程序更加高效、简洁。n指针就是内存地址,不同于通过变量名引指针就是内存地址,不同于通过变量名引用内存单元的直接访问方式,使用指针可用内存单元的直接访问方式,使用指针可实现对内存单元的间接访问。实现对内存单元的间接访问。n本章介绍指针的有关概念,介绍指针与数本章介绍指针的有关概念,介绍指针与数组的关系,介绍与函数的关系。组的关系,介绍与函数的关系。2本章的学习目标本章的学习目标n本章教学目的:理解指针的概念和内存访问的关系,掌握
2、本章教学目的:理解指针的概念和内存访问的关系,掌握指针的定义、引用。熟练使用指针访问基本类型的数据。指针的定义、引用。熟练使用指针访问基本类型的数据。理解指针与数组的关系,运用指针实现对数组的访问,包理解指针与数组的关系,运用指针实现对数组的访问,包括对一维数组和二维数组处理。理解指针与字符串(字符括对一维数组和二维数组处理。理解指针与字符串(字符数组)的关系,运用指针操作字符串。理解指针数组的概数组)的关系,运用指针操作字符串。理解指针数组的概念,能运用指针数组处理相关的数据类型,尤其是运用字念,能运用指针数组处理相关的数据类型,尤其是运用字符指针数组处理多个字符串。理解指针与函数的关系,运
3、符指针数组处理多个字符串。理解指针与函数的关系,运用指针实现函数调用。理解带参数的用指针实现函数调用。理解带参数的main函数作用及各个函数作用及各个参数的含义。参数的含义。n本章教学重点:指针的概念,指针与数组的关系。本章教学重点:指针的概念,指针与数组的关系。n本章教学难点:指针数组,指针与函数,多重指针。本章教学难点:指针数组,指针与函数,多重指针。3主要内容主要内容9.1 指针的基本概念指针的基本概念 9.2 指针与一维数组指针与一维数组 9.3 指针与字符串指针与字符串 9.4 指针与二维数组指针与二维数组 9.5 指针数组与多级指针的概念指针数组与多级指针的概念 9.6 指针与函数
4、指针与函数 9.7 命令行参数命令行参数 9.8 程序设计举例程序设计举例 49.1指针的基本概念指针的基本概念 n内存是计算机的重要组成部分,在程序的执行过程中,内存是计算机的重要组成部分,在程序的执行过程中,所用到的数据都存于内存中。所用到的数据都存于内存中。n内存单元的基本单位是字节,为方便对内存的访问,内内存单元的基本单位是字节,为方便对内存的访问,内存单元的每个字节都有一个编号,存单元的每个字节都有一个编号,这个编号就是内存的这个编号就是内存的地址。地址。nC程序中的每一个变量,在内存中都占用一定数量的内存程序中的每一个变量,在内存中都占用一定数量的内存单元。给变量赋值就是将数据存入
5、对应的内存单元,使单元。给变量赋值就是将数据存入对应的内存单元,使用变量时是按照变量所占用的内存单元的地址,从该地用变量时是按照变量所占用的内存单元的地址,从该地址所对应的内存单元中取出变量的值。址所对应的内存单元中取出变量的值。n因为我们是通过变量的地址来找到存储变量值的内存单因为我们是通过变量的地址来找到存储变量值的内存单元,从而取得了变量的值,元,从而取得了变量的值,所以将变量的地址又称为变所以将变量的地址又称为变量的指针量的指针。59.1指针的基本概念指针的基本概念 n如如右右图所示,整型变量图所示,整型变量i占占2000、2001两两个字节的内存,整型变量个字节的内存,整型变量j占占
6、2002、2003两个字节的内存,其内存单元中存放的是两个字节的内存,其内存单元中存放的是整型数据。而变量整型数据。而变量p占占3000、3001两个字两个字节的内存,其内存单元中存放的是变量节的内存,其内存单元中存放的是变量i的的地址地址2000(一个变量占多个字节的内存单(一个变量占多个字节的内存单元时,以首地址表示该变量的地址)。这元时,以首地址表示该变量的地址)。这种存放另一个变量的地址的变量称为指针种存放另一个变量的地址的变量称为指针变量。称变量变量。称变量p指向变量指向变量i,p中存储的是变中存储的是变量量i的指针。的指针。n对一个变量的访问(访问是指取出其值或对一个变量的访问(访
7、问是指取出其值或向它赋值)方式有两种:向它赋值)方式有两种:(1)直接访问直接访问:通过变量名访问,如通过通过变量名访问,如通过变量名变量名i直接访问直接访问i。(2)间接访问间接访问:通过指向该变量的指针变通过指向该变量的指针变量来访问,如通过量来访问,如通过p访问变量访问变量i。6指针变量的定义指针变量的定义 n指针变量是一类特殊的变量,其值是一个变量的地址。既指针变量是一类特殊的变量,其值是一个变量的地址。既然是变量,就需要在使用之前先对其定义,然后才可以使然是变量,就需要在使用之前先对其定义,然后才可以使用。用。n指针变量定义的一般形式:指针变量定义的一般形式:类型标识符类型标识符 *
8、标识符标识符;其中,其中,类型标识符类型标识符用于指出所定义指针变量可以指向用于指出所定义指针变量可以指向的变量类型,称为指针变量的的变量类型,称为指针变量的“基类型基类型”,标识符标识符是指针是指针变量名,变量名,“*”表示定义指针变量。表示定义指针变量。7指针变量的定义指针变量的定义 例如:例如:int *p1;/*定义指针变量p1,指向整型变量*/float *p2;/*定义指针变量p2,指向实型变量*/char *p3;/*定义指针变量p3,指向字符型变量*/n指针变量定义的同时也可以对其初始化,例如:int i;int *p=&i;这样定义的指针变量p,就指向整型变量i。8指针变量的
9、定义指针变量的定义 n定义指针变量时应该注意注意:(1)标识符前的“*”只是一个符号,表示其后的变量是一个指针变量。(2)指针变量的基类型必须与所指向的变量类型一致,否则会出错。例如:float x;int*p1=&x;是错误的。因为p1的基类型为整型,而变量x 是单精度类型,数据类型不一致。9指针变量的引用指针变量的引用 n(1)&:取地址运算符:取地址运算符,用于取变量的地址。,用于取变量的地址。n例如:例如:int i,*p1;p1=&i;取取i的地址赋给指针变量的地址赋给指针变量p1。n(2)*:指针运算符:指针运算符,用于访问指针变量所指向的变量。,用于访问指针变量所指向的变量。n例
10、如:例如:int i,*p1;p1=&i;*p1=100;则则*p1与与i等价,访问等价,访问i时时,可以用间接方式,用可以用间接方式,用*p1代表代表i,语句语句“*p1=100;”与与“i=100;”相同,为相同,为i赋值赋值100。10指针变量的引用指针变量的引用 若有:若有:int i=100;int*p1;p1=&i;则指针变量则指针变量p1指向变量指向变量i,对变量,对变量i有如下两种访问方式:有如下两种访问方式:(1)直接访问。)直接访问。如如 printf(“%d”,i);(2)通过指针变量间接访问。)通过指针变量间接访问。如如:printf(“%d”,*p1);119.1.2
11、指针变量的引用指针变量的引用#include int main()int i,j,*p;p=&i;/*p指向i*/i=10;printf(“%d,%dn”,i,*p);*p=100;printf(“%d,%dn”,i,*p);p=&j;*p=200;printf(“%d,%dn”,j,*p);return 0;程序运行结果为:程序运行结果为:10,10100,100200,200程序说明:程序说明:(1)将变量将变量i的地址赋给了指针变量的地址赋给了指针变量p之后,之后,*p与与i等价。等价。(2)语句语句“*p=100;”的作用是将的作用是将100存入由存入由p所指向的变量中,即存所指向的变
12、量中,即存入整型变量入整型变量i中。中。例例9.1:指针变量的引用指针变量的引用129.1.2指针变量的引用指针变量的引用#include int main()int num1=12,*p1;float num2=3.14,*p2;char ch=p,*p3;p1=&num1;p2=&num2;p3=&ch;printf(“num1=%d,*p1=%dn”,num1,*p1);printf(“num2=%4.2f,*p2=%4.2fn”,num2,*p2);printf(“ch=%c,*p3=%cn”,ch,*p3);return 0;程序的运行结果为:程序的运行结果为:num1=12,*p1
13、=12num2=3.14,*p2=3.14ch=p,*p3=p例例9.2 写出以下程序的运行结果。写出以下程序的运行结果。程序说明:程序说明:从程序的运行结果可以从程序的运行结果可以看出看出num1和和*p1、num2和和*p2、ch1和和*p3是等价的是等价的。139.1.2指针变量的引用指针变量的引用#include int main()int num1,num2;int*p1=&num1,*p2=&num2,*p;printf(“Input the first number:”);scanf(“%d”,p1);printf(“Input the second number:”);scan
14、f(“%d”,p2);printf(“num1=%d,num2=%dn”,num1,num2);if(*p1 *p2)p=p1;p1=p2;p2=p;printf(“min=%d,max=%dn”,*p1,*p2);return 0;程序运行结果:程序运行结果:Input the first number:9Input the first number:9Input the second number:6Input the second number:6num1=9,num2=6num1=9,num2=6min=6,max=9min=6,max=9例例9.3 使用指针变量求解:输入使用指针变量
15、求解:输入2个整数,按从小到大顺序输出。个整数,按从小到大顺序输出。14l程序说明:程序说明:l(1)程序中的)程序中的if语句,若语句,若*p1*p2(即(即num1num2),则交换指针,使),则交换指针,使p1指向变量指向变量num2(较小值),(较小值),p2指向变量指向变量num1(较大值)。(较大值)。l(2)“printf(“min=%d,max=%dn”,*p1,*p2);”语句,通过指针变量,间接访问变量的值。语句,通过指针变量,间接访问变量的值。l 本例的处理思路是:交换指针变量本例的处理思路是:交换指针变量p1和和p2的值,的值,而不是交换变量而不是交换变量num1和和n
16、um2的值(变量的值(变量num1和和num2并未交换,仍保持原值),最后通过指针变并未交换,仍保持原值),最后通过指针变量输出处理结果。量输出处理结果。例例9.3 使用指针变量求解:输入使用指针变量求解:输入2个整数,按从小到大顺序输出。个整数,按从小到大顺序输出。159.2 指针与一维数组指针与一维数组 数组和指针有密切的关系,数组和指针有密切的关系,数组名代表数组数组名代表数组的首地址的首地址。当一个指针指向数组后,对数组元素的访问,当一个指针指向数组后,对数组元素的访问,既可以使用数组下标,也可以使用指针。既可以使用数组下标,也可以使用指针。用指针访问数组元素,程序的效率更高;用用指针
17、访问数组元素,程序的效率更高;用下标访问数组元素程序更清晰。下标访问数组元素程序更清晰。169.2.1 指向数组元素的指针指向数组元素的指针 在在C语言中,当一个数组语言中,当一个数组a被定义后,数组名被定义后,数组名a本身就代表了该数组的本身就代表了该数组的首地址,并且它是一个地址常量,数组元素的地址可以通过数组名首地址,并且它是一个地址常量,数组元素的地址可以通过数组名a加下加下标值来取得。标值来取得。a即即a+0代表数组元素代表数组元素a0的地址,的地址,a+1代表数组元素代表数组元素a1的地址,的地址,a+2代表数组元素代表数组元素a2的地址,的地址,。若定义一个指针变量,使其指向一个
18、数组,则该指针变量称为指若定义一个指针变量,使其指向一个数组,则该指针变量称为指向数组的指针变量,其定义与指向普通变量的指针变量的定义方法是向数组的指针变量,其定义与指向普通变量的指针变量的定义方法是一样的。一样的。例例如:如:int a10,*p;则:则:pa;或者:或者:p=&a0;上面上面两个语句是等价的,都表示把数组两个语句是等价的,都表示把数组a的首地址赋给指针变量的首地址赋给指针变量p。17指针变量也可以指向数组的其它元素。例如:指针变量也可以指向数组的其它元素。例如:int*p1,*p2;int a10=1,2,3,4,5,6,7,8,9,10;此后可以赋值:此后可以赋值:p1=
19、&a0;p2=&a4;完成了赋值之后,指针完成了赋值之后,指针p1指向数组指向数组a的首元素,的首元素,p2指向数组元素指向数组元素a4。对于上面所写对于上面所写&a0的表达形式,由于数组元素访问运算的表达形式,由于数组元素访问运算符符的优先级更高,所以这里不必写成的优先级更高,所以这里不必写成&(a0)的形式。的形式。9.2.1 指向数组元素的指针指向数组元素的指针189.2.2 通过指针引用数组元素通过指针引用数组元素 数组定义和初始化之后,数组元素可以通过数组的下标、数组名或指向数组的指针变量来引用。若定义一个一维数组:int a10=1,2,3,4,5,6,7,8,9,10;可以通过数
20、组的下标访问数组元素:如:printf(“%d”,a5);也可以通过数组名访问数组元素:如:也可以通过数组名访问数组元素:如:*(a+0)即即*(a)与与a0相等,相等,*(a+1)与与a1相等,相等,*(a+2)与与a2相等,相等,*(a+i)与与ai相等,相等,。但使用数组名时,注意不能用但使用数组名时,注意不能用a+的方式,因为的方式,因为a是是地址常量,常量是不能被重新赋值的。地址常量,常量是不能被重新赋值的。19 同样,若定义指针变量同样,若定义指针变量p(int*p;),并使),并使p指向数指向数组组a(即(即p=a),则可以用指针变量来访问数组元素,如),则可以用指针变量来访问数
21、组元素,如右图所示。右图所示。p指向数组的第一个元素指向数组的第一个元素a0,则,则p+1指向数指向数组的下一个元素组的下一个元素a1,p+2指向数组元素指向数组元素a2,p+i指向数组元素指向数组元素ai,。可以使用可以使用*(p+i)访问元素访问元素ai。p+i等价于等价于a+i,都表示元素,都表示元素ai的地址。的地址。指向数组的指针变量也可以带下标,如指向数组的指针变量也可以带下标,如pi与与*(p+i)等价,表示元素等价,表示元素ai。9.2.2 通过指针引用数组元素通过指针引用数组元素数组元素数组元素ai的的4种引用方式:种引用方式:ai、*(a+i)、*(p+i)、pi。引用引用
22、数组元素数组元素ai地址的地址的4种方式为:种方式为:&ai、a+i、p+i、&pi。20 另另外外,在在使使用用指指向向数数组组的的指指针针变变量时,注意对指针变量量时,注意对指针变量p+1的理解。的理解。若若数数组组元元素素是是int型型,p+1所所表表示示的的地地址址是是p的的地地址址值值加加2个个字字节节;若若数数组组元元素素是是float型型,p+1所所表表示示的的地地址址是是p的的地地址址值值加加4个个字字节节;若若数数组组元元素素是是char型型,p+1所所表表示示的的地地址址是是p的地址值加的地址值加1个字节。个字节。9.2.2 通过指针引用数组元素通过指针引用数组元素21 当
23、当指指针针变变量量p中中存存储储的的是是数数组组a的的首首地地址址(p=a)时时,执执行行p+后后,p中中存存储储的的是是数数组组元元素素a1的的地地址址,再再执执行行p+后后,p中中存存储储的的是是数数组元素组元素a2的地址,的地址,。若若数数组组元元素素是是int型型,执执行行p+后后,p中中存存储储的的地地址址是是p中中原原来来存存储储的的地地址址值值加加2个个字字节节;若若数数组组元元素素是是float型型,执执行行p+后后,p中中存存储储的的地地址址是是p中中原原来来存存储储的的地地址址值值加加4个个字字节节(如如右右图图);若若数数组组元元素素是是char型型,执执行行p+后后,p
24、中中存存储储的的地地址址是是p中中原原来来存存储储的的地地址址值值加加1个个字节。字节。若若p中中存存储储的的是是元元素素ai(i1)的的地地址址,根根据据上上面面的的叙叙述述,读读者者可可以以思思考考如如何何理理解解p-1、p-。float *pp-1pp+1p+2*(p-1)*p*(p+1)*(p+2)9.2.2 通过指针引用数组元素通过指针引用数组元素229.2.2 通过指针引用数组元素通过指针引用数组元素int int main()int a10,*p=a,i,sumi,sum;printf(“Input 10 numbers:”);for(i=0;i10;i+)scanf(“%d”,
25、p+i);/*使用指针变量来输入数组元素的值使用指针变量来输入数组元素的值*/printf(“array array a:”);for(i=0;i10;i+)printf(“%d”,*(p+i);/*使用指向数组的指针变量输出数组元素的值使用指向数组的指针变量输出数组元素的值*/sum=sum+sum=sum+*(p+i);printf(“n sum=%d n sum=%d n”,sum,sum);return 0;return 0;程序运行情况:程序运行情况:Input 10 numbers:0 1 2 3 4 5 6 7 8 9 array a:0 1 2 3 4 5 6 7 8 9sum
26、=45例例9.4 使用指向数组的指针变量来引用数组元素。使用指向数组的指针变量来引用数组元素。23#include int int main()int a10,*p=a,i,sum,sum;printf(“Input 10 numbers:”);for(i=0;i10;i+,p+)scanf(“%d”,p);printf(“array array a:”);p=a;/*使使p重新指向数组的第一个元素重新指向数组的第一个元素*/for(i=0;i10;i+,p+)printf(“%d”,*p);sum=sum+sum=sum+*(p+i);printf(“n sum=%d n sum=%d n”
27、,sum,sum);return 0;return 0;程序说明:程序说明:(1)用指针变量直接指向数组元用指针变量直接指向数组元素,不必每次都重新计算地址。这素,不必每次都重新计算地址。这种有规律地改变地址值(种有规律地改变地址值(p+)的)的方法能较好地提高执行效率。方法能较好地提高执行效率。(2)用下标法比较直观,能直接用下标法比较直观,能直接知道操作的是数组的第几个元素。知道操作的是数组的第几个元素。9.2.2 通过指针引用数组元素通过指针引用数组元素例例9.4程序也可写为:程序也可写为:249.2.3 指针使用的几个细节指针使用的几个细节1空指针空指针 空指针是个特殊的值,也是唯一对
28、任何指针类型都合法的值。一个指针变空指针是个特殊的值,也是唯一对任何指针类型都合法的值。一个指针变量具有空值,表示它当时没有被赋予有意义的地址,处于闲置状态。空指针值量具有空值,表示它当时没有被赋予有意义的地址,处于闲置状态。空指针值用用0 0表示,这个值绝不会是任何程序对象的地址。但给一个指针变量赋值,说明表示,这个值绝不会是任何程序对象的地址。但给一个指针变量赋值,说明该指针变量不再是一个不定值,而是一个有效的值。该指针变量不再是一个不定值,而是一个有效的值。为了提高程序的可读性,标准库定义了一个与为了提高程序的可读性,标准库定义了一个与0等价的符号常量等价的符号常量NULL,程序里可以写
29、:程序里可以写:p=NULL;或者:或者:p=0;这两种写法都将指针这两种写法都将指针p置为空指针值。前一种写法使读程序的人容易意置为空指针值。前一种写法使读程序的人容易意识到这里是一个指针赋值,采用前一种写法时必须通过识到这里是一个指针赋值,采用前一种写法时必须通过#include 包含相应的包含相应的标准头文件,即标准头文件,即#include。259.2.3 指针使用的几个细节指针使用的几个细节2指针初始化指针初始化 在定义指针变量时,可以用合法的指针值对它进行初始化。在定义指针变量时,可以用合法的指针值对它进行初始化。例如下面定义:例如下面定义:int n,*p=&n,*q=NULL;
30、执行p+(或 p+=1)后,p指向数组的下一个元素。*p+相当于*(p+)。因为,*和+同优先级,+是右结合运算符。*(p+)与*(+p)的作用不同。*(p+):先取*p,再使p加1。*(+p):先使p加1,再取*p。(*p)+表示p指向的元素值加1。3设指针设指针p指向数组指向数组a(p=a),则有如下事实:),则有如下事实:269.2.3 指针使用的几个细节指针使用的几个细节*(p-)相当于ai-,先取*p,再使p减1。*(+p)相当于a+i,先使p加1,再取*p。*(-p)相当于a-i,先使p减1,再取*p。4如果如果p当前指向数组当前指向数组a的第的第i个元素,则有如下事实:个元素,则
31、有如下事实:q1 p1表示q1 所指元素位于p1 所指元素之后,q1 p1 表示q1 所指元素位于p1 所指元素之前。如果两个指针不指向同一个数组,对它们的比较也没有意义。5如果两个指针如果两个指针q1和和 q1指向同一个数组,那么可以对指向同一个数组,那么可以对两个指针进行比较:两个指针进行比较:例如“n=p2 p1;”,当两个指针不指向同一数组时,求它们的差就完全没有意义了。6当两个指针指向同一数组时,可以求它们的差,得到的结当两个指针指向同一数组时,可以求它们的差,得到的结果是对应的数组元素的下标之差果是对应的数组元素的下标之差(可能是一个负数)。279.3 指针与字符串指针与字符串 在
32、语言中,既可以用字符数组表示字符串,也可用字符指针变量来表示字符串。既可以逐个字符引用字符串,也可以整体引用字符串。字符串在内存中的起始地址称为字符串的指针,可以定义一个字符指针变量指向一个字符串。289.3.1 字符串的表现形式字符串的表现形式 在在C语言中,有两种方式可以操作字符串:语言中,有两种方式可以操作字符串:1.使用字符数组使用字符数组#include int main()char string =“she is our teacher“;printf(%sn,string);return 0;例例9.5 使用字符数组来输出一串字符串。程序运行输出:she is our teach
33、er292.使用字符指针使用字符指针#include int main()char*string=“she is our teacher”;printf(“%sn”,string);return 0;程序中程序中stringstring是一个指针变量,是一个指针变量,语句:语句:char*string=“she is our teacher”;char*string=“she is our teacher”;等价于等价于:char *string;string=“she is our teacher”;上面语句把字符串常量的首地址赋给指针上面语句把字符串常量的首地址赋给指针string。不能理
34、解为把字符串常。不能理解为把字符串常量赋值给指针变量。若写成下面形式量赋值给指针变量。若写成下面形式是错误的是错误的:*string=“she is our teacher”;9.3.1 字符串的表现形式字符串的表现形式例例9.6 使用字符指针来输出一串字符串。使用字符指针来输出一串字符串。30 从以上两个例子,可以看出:(1)字符数组和字符指针的概念不同。(2)字符指针指向字符串,在C语言中,字符串按数组方式处理,因此,字符数组和字符指针的访问方式相同。9.3.1 字符串的表现形式字符串的表现形式 例如,无论使用字符数组或是字符指针引用字符串,都可以使用例如,无论使用字符数组或是字符指针引用
35、字符串,都可以使用%s格式控制符进行整体输入输出。格式控制符进行整体输入输出。注意注意注意注意,如果不是字符数组,而是整型、实型等数字型数组,不能用,如果不是字符数组,而是整型、实型等数字型数组,不能用%s,只能逐个元素处理。,只能逐个元素处理。319.3.2 字符指针作函数参数字符指针作函数参数 将一个字符串从一个函数传递到另一个函数,可以用字符数组名或字符指针变量作参数。有以下四种情况:1实参和形参都为字符数组。实参和形参都为字符数组。2实参为字符指针,形参为数组名。实参为字符指针,形参为数组名。3实参和形参都为字符指针变量。实参和形参都为字符指针变量。4实参为数组名,形参为字符指针变量。
36、实参为数组名,形参为字符指针变量。32例例9.7 用函数调用实现字符串的复制用函数调用实现字符串的复制1.实参和形参都为字符数组实参和形参都为字符数组#include v void copy_string(char str1,char str2)int i=0;while(str1i!=0)str2i=str1i;i+;str2i=0;int int main()char a2020=“I love china!love china!”;char b2020=“good!”;printf(“a=%sn b=%sn”,a,b);copy_string(a,b);printf(“a=%sn b=%
37、sn”,a,b);return 0;return 0;9.3.2 字符指针作函数参数字符指针作函数参数 332.实参为字符指针,形参为数组名实参为字符指针,形参为数组名#include void copy_string(char str1,char str2)int i=0;while(str1i!=0)str2i=str1i;i+;str2i=0;int int main()int i;char*a=“I love china!love china!”;char*b=“good!”;printf(“a=%sn b=%sn”,a,b);copy_string(a,b);for(i=0;*(a+
38、for(i=0;*(a+i)!=)!=00;i+)i+)putchar(*(a+putchar(*(a+i););printf(“n”);for(i=0;*(b+for(i=0;*(b+i)!=)!=00;i+)i+)putchar(*(b+putchar(*(b+i););return 0;return 0;例例9.7 用函数调用实现字符串的复制用函数调用实现字符串的复制9.3.2 字符指针作函数参数字符指针作函数参数 343.实参和形参都为字符指针变量实参和形参都为字符指针变量#include void copy_string copy_string(char*str1,char*str2
39、)for(;*str1str1!=0;str1+,str2+)*str2=*str1;*str2=0;例例9.7 用函数调用实现字符串的复制用函数调用实现字符串的复制9.3.2 字符指针作函数参数字符指针作函数参数 int main()char*a=“I love china!”;char*b=“good!”;for(i=0;*(a+i)!=0;i+)putchar(*(a+i);printf(“n”);for(i=0;*(b+i)!=0;i+)putchar(*(b+i);printf(“n”);copy_string(a,b);puts(a);puts(b);return 0;354.实参
40、为数组名,形参为字符指针变量实参为数组名,形参为字符指针变量#include void copy_string(char*str1,char*str2)int i=0;for(;(*(str2+i)=*(str1+i)!=0;i+);/*循环体为空语句循环体为空语句*/int int main()char a a20=“I love china!love china!”;char b b20=“good!good!”;printf(“a=%sn b=%sn”,a,b);copy_string(a a,b b);pu uts s(a);puts(b););puts(b);return 0;ret
41、urn 0;程程序序说说明明:以以上上四四种种方方式式实实现现相相同同的的功功能能,即即把把a a中中的的字字符符串串拷拷贝贝到到b b中中,不不同同的的地地方是拷贝函数参数的方式不同。方是拷贝函数参数的方式不同。在第四种方式中,语句在第四种方式中,语句for(;(*(str2+i)=*(str1+i)!=0;i+);的的执执行行过过程程为为:首首先先将将源源串串中中的的当当前前字字符符,复复制制到到目目标标串串中中;然然后后判判断断该该字字符符是是否否是是字字符符串串结结束束标标志志。如如果果不不是是,则则相相对对位位置置变变量量i的的值值增增1,以以便便复复制制下下一一个个字字符符;否否则
42、则结结束束循循环环。其其特特点点是是:先先复复制制、后后判判断断,循循环环结结束前,结束标志已经复制了。束前,结束标志已经复制了。例例9.7 用函数调用实现字符串的复制用函数调用实现字符串的复制9.3.2 字符指针作函数参数字符指针作函数参数 上述四个程序的运行结果都是:上述四个程序的运行结果都是:a=I love china!a=I love china!b=I love china!b=I love china!369.3.3 字符指针变量与字符数组的区别字符指针变量与字符数组的区别 虽然用字符指针变量和字符数组都能实现字符串的存储虽然用字符指针变量和字符数组都能实现字符串的存储和处理,但
43、二者是有区别的:和处理,但二者是有区别的:(1)存储内容不同)存储内容不同 字符指针变量中存储的是字符串的首地址,而字符数组字符指针变量中存储的是字符串的首地址,而字符数组中存储的是字符串本身(数组的每个元素存放一个字符)。中存储的是字符串本身(数组的每个元素存放一个字符)。(2)赋值方式不同)赋值方式不同 对字符指针变量,可采用下面的赋值语句赋值:对字符指针变量,可采用下面的赋值语句赋值:char *pointer;pointer=This is a example.;而字符数组,虽然可以在定义时初始化,但不能用赋值语而字符数组,虽然可以在定义时初始化,但不能用赋值语句整体赋值。下面的用法是
44、非法的:句整体赋值。下面的用法是非法的:char char_array20;char_array=This is a example.;/*非法用法非法用法*/379.3.3 字符指针变量与字符数组的区别字符指针变量与字符数组的区别(3)指针变量的值是可以改变的,字符指针变量也不)指针变量的值是可以改变的,字符指针变量也不例外;而数组名代表数组的起始地址,是一个常量,而例外;而数组名代表数组的起始地址,是一个常量,而常量是不能被改变的。常量是不能被改变的。例如:例如:char*a=“abcdefg”;a=a+3;puts(a);执行后输出执行后输出“defg”。但下面的执行后却要出错:但下面的
45、执行后却要出错:char a6=“china”;a=a+3;puts(a);因为因为a=a+3是非法的。是非法的。389.4 指针与二维数组指针与二维数组 指针可以指向一维数组,同样也可以指向二维数组,或指向更高维数组,但指向二维数组或多维数组的指针更复杂一些。399.4.1 二维数组的指针二维数组的指针 二二维维数数组组是是一一个个由由类类型型相相同同的的变变量量构构成成的的集集合合,其其元元素素以以行行优优先先顺顺序序存存放放在在内内存存中中。可可以以将将二二维维数数组组看看成成是是由由几几个个一一维维数数组组作作为为元元素素组组成的一个一维数组。成的一个一维数组。例如下面定义的数组例如下
46、面定义的数组a a:int a34=1=1,2 2,3,3,,44,5 5,6 6,7 7,88,9 9,1010,1111,1212;由由1212个个整整型型变变量量构构成成,这这1212个个数数组组元元素素按按行行顺顺序序存存放放,如如右右图图所所示示。可可以以将将a a看看成成是是一一维维数数组组,它它由由a0、a1、a2三三个个数数组组元元素素组组成成;且且a0、a1、a2 也是一维数组,长度为。也是一维数组,长度为。二二维维数数组组的的地地址址或或指指针针可可以以分分成成两两种种:一一种种用用来来表表示示真真实实的的数数组组元元素素的的地地址址,称称为为元元素素地地址址,也也就就是是
47、元元素素指指针针;另另一一种种用用来来表表示示数数组组的的每一行的地址,称为每一行的地址,称为行地址行地址,也就是行指针。,也就是行指针。40 二二维维数数组组a中中元元素素aij的的地地址址或或指指针针可可以以用用&aij来来表表示示。由由于于我我们们将将二二维维数数组组看看成成是是由由几几个个一一维维数数组组作作为为元元素素组组成成的的一一个个一一维维数数组组,将将二二维维数数组组的的每每一一行行看看成成是是一一个个一一维维数数组组,ai是是一一维维数数组组名名,由由一一维维数数组组与与指指针针的的关关系系知知,元素元素aij的地址或指针可以用的地址或指针可以用ai+j来表示来表示。语语言
48、言规规定定数数组组名名代代表表数数组组的的首首地地址址。二二维维数数组组名名a是是一一个个行行地地址址,a+0a+0、a+1a+1、a+2a+2分分别别是是下下标标为为0 0、1 1、2 2行行的的地地址址,即即以以a0a0、a1a1、a2a2为一维数组名的行地址。为一维数组名的行地址。即即a a(a+0a+0)是是一一维维数数组组a0a0的的首首地地址址,a+1a+1是是一一维维数数组组a1a1的的首首地地址址,a+2a+2是是一一维维数数组组a2a2的首地址,的首地址,如右图所示。如右图所示。9.4.1 二维数组的指针二维数组的指针 41 如如果果b是是一一维维数数组组名名,bi为为b数数
49、组组的的一一个个元元素素,那那么么有有bi等等价价于于*(b+i)。同同样样,a是是二二维维数数组组名名,ai为为a数数组组的的一一个个元元素素(将将a看看成成一一维维数数组组时时,ai为为a数数组组的一个元素),也有的一个元素),也有ai 等价于等价于*(a+i)。所所以以二二维维数数组组a中中元元素素aij的的地地址址或或指指针针既既可可以以用用ai+j来来表表示示,也也可可以以用用*(a+i)+j来表示。来表示。9.4.1 二维数组的指针二维数组的指针 综上所述,二维数组综上所述,二维数组a中元素中元素aij的的地址或指针可以表示成以下几种形式:地址或指针可以表示成以下几种形式:&aij
50、、ai+j、*(a+i)+j 对应地,数组元素对应地,数组元素aij 可以表示成以可以表示成以下几种形式:下几种形式:aij、*(ai+j)、*(*(a+i)+j)429.4.2 行指针变量行指针变量 二二维维数数组组是是由由相相同同类类型型的的一一维维数数组组作作为为元元素素而而构构成成的的一一维数组,所谓行指针变量就是用来存放维数组,所谓行指针变量就是用来存放“行地址行地址”的变量。的变量。行指针变量的定义形式如下:行指针变量的定义形式如下:类型标识符类型标识符 (*行指针变量名行指针变量名)数组长度数组长度;注意:注意:“*行指针变量名行指针变量名”外的括号不能缺,否则成了指针数外的括号