C语言指针精品课件

上传人:夏** 文档编号:578668659 上传时间:2024-08-24 格式:PPT 页数:107 大小:1.48MB
返回 下载 相关 举报
C语言指针精品课件_第1页
第1页 / 共107页
C语言指针精品课件_第2页
第2页 / 共107页
C语言指针精品课件_第3页
第3页 / 共107页
C语言指针精品课件_第4页
第4页 / 共107页
C语言指针精品课件_第5页
第5页 / 共107页
点击查看更多>>
资源描述

《C语言指针精品课件》由会员分享,可在线阅读,更多相关《C语言指针精品课件(107页珍藏版)》请在金锄头文库上搜索。

1、C程序设计快速进阶大学教程2024/8/242第第11章章 指针指针本章要点本章要点指针概念指针概念指针与数组指针与数组指针与函数指针与函数字符串字符串动态空间管理动态空间管理2021/6/162C程序设计快速进阶大学教程2024/8/24311 指针指针知识点知识点指针概念指针概念指向数组的指针、指针数组指向数组的指针、指针数组指针做参数、指针做为函数值、指向函数的指针指针做参数、指针做为函数值、指向函数的指针字符串字符串动态空间管理动态空间管理2021/6/163C程序设计快速进阶大学教程2024/8/24411.1 理解指针理解指针当问路时,经常听到这样的回答:当问路时,经常听到这样的回

2、答:“向前走过向前走过3个路个路口右转,再过两个路口左转,再前行口右转,再过两个路口左转,再前行200米。米。”当在图书馆中找一本时,经常是这样找:当在图书馆中找一本时,经常是这样找:“第五排第五排书架,从上向下数第二层,左数第书架,从上向下数第二层,左数第6本。本。” 老师提问学生,在不知道学生姓名的情况下,经常老师提问学生,在不知道学生姓名的情况下,经常说:说:“第第4排左数第二个同学。排左数第二个同学。” 上述例子说明对一个事务的访问,当不能够通过名上述例子说明对一个事务的访问,当不能够通过名称直接访问,只能够通过其位置进行访问。称直接访问,只能够通过其位置进行访问。 C程序同样的道理,

3、前面的章节对数据的访问是通程序同样的道理,前面的章节对数据的访问是通过变量名称实现的,但是,有时候不知道其名称,过变量名称实现的,但是,有时候不知道其名称,甚至其没有名称,这时候只能通过该数据所在的地甚至其没有名称,这时候只能通过该数据所在的地址进行访问。址进行访问。2021/6/164C程序设计快速进阶大学教程2024/8/24511.2 指向变量的指针指向变量的指针C语言中定义一个变量时,例如:语言中定义一个变量时,例如: int i1=3;描述了变量相关的描述了变量相关的3方面的属性:方面的属性:值、地值、地址、类型址、类型。1. 值为值为3,通过变量访问,如,通过变量访问,如i1+52

4、. 地址为地址为0012ff78(32位机器,位机器,0012ff78为为16进制数),进制数),占用内存空间的位置,通过占用内存空间的位置,通过&i1访问,访问,&在在scanf语句中语句中使用过。使用过。3. 类型为类型为int,决定了其能够参加的运算,同时也决定了其占,决定了其能够参加的运算,同时也决定了其占用空间的大小(从起始地址开始占用的连续字节数),用空间的大小(从起始地址开始占用的连续字节数),占用空间的大小通过占用空间的大小通过sizeof运算符,在运算符,在vc中中sizeof(i1)为为4个字节。个字节。2021/6/165C程序设计快速进阶大学教程2024/8/24611

5、.2 指向变量的指针指向变量的指针把变量把变量i1的地址存放于指针变量的地址存放于指针变量pi1中中 2021/6/166C程序设计快速进阶大学教程2024/8/24711.2.1 指针变量的定义指针变量的定义指针变量定义的一般形式为:指针变量定义的一般形式为: 类型说明符类型说明符 *变量名变量名;例如:例如:int *pi1;对指针变量的定义包括三个内容:对指针变量的定义包括三个内容:1. 指针类型说明,指针类型说明,*表示这是一个指针变量;表示这是一个指针变量;2. 指针变量名,指针变量名,pi1为指针变量名;为指针变量名;3. 指针所指向的变量的数据类型,指针所指向的变量的数据类型,i

6、nt为指针变量所指向的变为指针变量所指向的变量的数据类型,说明量的数据类型,说明pi1只能储存整型变量的地址。只能储存整型变量的地址。再如:再如:float *pf1; /*pf1是指向浮点变量的指针变量是指向浮点变量的指针变量*/char *pc1 /*pc1是指向字符变量的指针变量是指向字符变量的指针变量*/2021/6/167C程序设计快速进阶大学教程2024/8/24811.2.2 指针变量的引用指针变量的引用 指针变量同普通变量一样,使用之前不仅要定指针变量同普通变量一样,使用之前不仅要定义说明,而且必须赋予具体的值。义说明,而且必须赋予具体的值。 未经赋值的指针变量不能使用,否则将

7、造成系未经赋值的指针变量不能使用,否则将造成系统混乱,甚至死机。(统混乱,甚至死机。(问路时别人告诉你一个不存问路时别人告诉你一个不存在的地址,会怎么样?在的地址,会怎么样?)2021/6/168C程序设计快速进阶大学教程2024/8/24911.2.2 指针变量的引用指针变量的引用 和指针相关有两个运算符和指针相关有两个运算符&和和*:1. &:取地址运算符。:取地址运算符。其一般形式为:其一般形式为: &变量名变量名 取一个内存变量的地址。取一个内存变量的地址。2. *:指针运算符(或称:指针运算符(或称“间接访问间接访问” 运算符)。运算符)。其一般形式为:其一般形式为: *指针变量名指

8、针变量名通过指针变量间接访问指针变量所指向变量的数据。通过指针变量间接访问指针变量所指向变量的数据。int i1; int * pi1; pi1=&i1;int i2=*pi1+1; 此处此处*代表间接访问运算符,取指针变量代表间接访问运算符,取指针变量pi1所指向的变量所指向的变量i1的值(对的值(对i1间接访问)加间接访问)加1赋值给变量赋值给变量i2。此语句结果完。此语句结果完全等价于:全等价于: int i2=i1+1;2021/6/169C程序设计快速进阶大学教程2024/8/241011.2.2 指针变量的引用指针变量的引用指针变量说明:指针变量说明:1. 对对*要区别类型说明符与

9、间接访访问符。要区别类型说明符与间接访访问符。2. 不能用一个数给指针变量赋值,下面赋值是错误的:不能用一个数给指针变量赋值,下面赋值是错误的:int *pi1; pi1=20;但是,指针可用但是,指针可用0赋值,代表空指针,哪里也不指向。赋值,代表空指针,哪里也不指向。3. 给指针变量赋值时,指针变量前不能加给指针变量赋值时,指针变量前不能加“*”说明符,下面说明符,下面的写法是错误的:的写法是错误的: int i1; int *pi1; *pi1=&i1;指针变量指针变量pi1前面加前面加*就代表间接访问了,代表就代表间接访问了,代表i1。2021/6/1610C程序设计快速进阶大学教程2

10、024/8/241111.2.2 指针变量的引用指针变量的引用指针变量说明:指针变量说明:4. 指针变量未指向具体有效地址,间接访问会有问题指针变量未指向具体有效地址,间接访问会有问题 int *pi1; /* 指针变量指针变量pi1未赋值,不知道指向哪里未赋值,不知道指向哪里*/ *pi1=200; /* 向向pi1所指向的地址空间赋值所指向的地址空间赋值200 */(随机给你一个账户,存钱后怎样取呢?随机给你一个账户,存钱后怎样取呢?)判定一个指针变量是否指向有效空间:判定一个指针变量是否指向有效空间:int *pi1=0;if(pi1!=0) *pi1=200;省略号部分,若未使省略号部

11、分,若未使pi1指向有效空间,这对指向有效空间,这对*pil的赋值就不的赋值就不会执行。会执行。2021/6/1611C程序设计快速进阶大学教程2024/8/241211.2.2 指针变量的引用指针变量的引用指针变量说明:指针变量说明:5. 指针变量的值是可以改变的指针变量的值是可以改变的int i1=3,i2=4,*pi1;pi1=&i1;i2=i2+*pi1;2021/6/1612C程序设计快速进阶大学教程2024/8/241311.2.2 指针变量的引用指针变量的引用指针变量说明:指针变量说明:5. 指针变量的值是可以改变的指针变量的值是可以改变的pi1=&i2;改变指针变量改变指针变量

12、pi1指向指向i2 2021/6/1613C程序设计快速进阶大学教程2024/8/241411.2.2 指针变量的引用指针变量的引用指针变量说明:指针变量说明:6.指针变量只能用同类型的地址赋值指针变量只能用同类型的地址赋值float *pf1; /*pf1是指向浮点变量的指针变量是指向浮点变量的指针变量*/char c1; /*字符变量字符变量*/pf1=&c1;pf1只能存储只能存储float数据的地址,用字符型数据地址赋值是错误数据的地址,用字符型数据地址赋值是错误的。的。2021/6/1614C程序设计快速进阶大学教程2024/8/241511.2.2 指针变量的引用指针变量的引用指针

13、变量说明:指针变量说明:7. 同类型指针变量间可以相互赋值同类型指针变量间可以相互赋值例例11.1 交换指针变量交换指针变量#include int main() int i1=3,i2=4; int *pi1,*pi2,*pi3; pi1=&i1; pi2=&i2;pi3=0; /*交换指针变量交换指针变量*/ pi3=pi1; pi1=pi2; pi2=pi3; printf(i1=%dni2=%dn,i1,i2); printf(*pi1=%dn*pi2=%dn,*pi1,*pi2); return 0; 程序运行结果:程序运行结果:i1=3i2=4*pi1=4*pi2=32021/6/

14、1615C程序设计快速进阶大学教程2024/8/241611.2.2 指针变量的引用指针变量的引用指针变量说明:指针变量说明:7. 同类型指针变量间可以相互赋值同类型指针变量间可以相互赋值例例11.1 交换指针变量交换指针变量2021/6/1616C程序设计快速进阶大学教程2024/8/241711.2.2 指针变量的引用指针变量的引用指针变量说明:指针变量说明:7. 同类型指针变量间可以相互赋值同类型指针变量间可以相互赋值例例11.2 交换指针变量所指向的数据交换指针变量所指向的数据#include int main() int i1=3,i2=4; int *pi1,*pi2; int i

15、Temp=0; pi1=&i1; pi2=&i2; /*交换指针变量所指向的数据交换指针变量所指向的数据*/ iTemp=*pi1; *pi1=*pi2; *pi2=iTemp; printf(i1=%dni2=%dn,i1,i2); printf(*pi1=%dn*pi2=%dn,*pi1,*pi2); return 0;程序运行结果:程序运行结果:i1=4i2=3*pi1=4*pi2=32021/6/1617C程序设计快速进阶大学教程2024/8/241811.2.2 指针变量的引用指针变量的引用指针变量说明:指针变量说明:7. 同类型指针变量间可以相互赋值同类型指针变量间可以相互赋值例例

16、11.2 交换指针变量所指向的数据交换指针变量所指向的数据2021/6/1618C程序设计快速进阶大学教程2024/8/2419课堂练习课堂练习 1. 指针变量存储的是什么?指针变量存储的是什么?2021/6/1619C程序设计快速进阶大学教程2024/8/242011.3 数组与指针数组与指针 一一个个变变量量有有一一个个地地址址,一一个个数数组组包包含含若若干干元元素素,每每个个数数组组元元素素都都在在内内存存中中占占用用存存储储单单元元,它它们们都都有有相相应应的的地地址址。所所谓谓数数组组的的指指针针是是指指数数组组的的起起始始地址,数组元素的指针是数组元素的地址。地址,数组元素的指针

17、是数组元素的地址。 对对数数组组元元素素也也可可以以采采用用指指针针进进行行访访问问,效效率率相相对更高。对更高。2021/6/1620C程序设计快速进阶大学教程2024/8/242111.3.1 一维数组与指针一维数组与指针一个数组是由连续的一块内存单元组成的。一个数组是由连续的一块内存单元组成的。数组名就是这块连续内存单元的首地址(常量)。数组名就是这块连续内存单元的首地址(常量)。int iArr5=1,2,3,4,5; int *pi; pi=&iArr0;2021/6/1621C程序设计快速进阶大学教程2024/8/242211.3.1 一维数组与指针一维数组与指针 C语言规定,数组

18、名代表数组的首地址,也语言规定,数组名代表数组的首地址,也就是第就是第0号元素的地址。因此,下面两个语句等价:号元素的地址。因此,下面两个语句等价: pi=&iArr0; pi=iArr; iArr数组名是整型数组名是整型常量地址常量地址 int i; iArr=&i;/*不可以,因为不可以,因为iArr为常量为常量*/2021/6/1622C程序设计快速进阶大学教程2024/8/242311.3.1 一维数组与指针一维数组与指针1. 指针相关的运算符指针相关的运算符(1) 取地址运算符取地址运算符&:单目运算符:单目运算符(注意其优先级注意其优先级),其结合性为自右至左,其功能是取变量的地,

19、其结合性为自右至左,其功能是取变量的地址。址。(2) 间接访问运算符间接访问运算符*:单目运算符,其结合性为:单目运算符,其结合性为自右至左,用来表示指针变量所指的变量。自右至左,用来表示指针变量所指的变量。(3) 赋值运算符赋值运算符=:可以给指针变量赋值。:可以给指针变量赋值。(4) 算术运算符算术运算符+、-、+、-。 +:地址表达式(:地址表达式(pi)+ 整型表达式(整型表达式(in),),结果为在结果为在pi地址值位置跳过地址值位置跳过in(pi所指类型字所指类型字节数)个字节后的地址。节数)个字节后的地址。2021/6/1623C程序设计快速进阶大学教程2024/8/242411

20、.3.1 一维数组与指针一维数组与指针1. 指针相关的运算符指针相关的运算符-:地址表达式(:地址表达式(pi)- 整型表达式(整型表达式(in),结果为),结果为在在pi地址值位置跳回地址值位置跳回in(pi所指类型字节数)所指类型字节数)个字节后的地址。个字节后的地址。-:地址表达式(:地址表达式(pi1)-地址表达式(地址表达式(pi12),结果),结果为在为在pi2和和pi1相差的字节数相差的字节数(pi1所指类型字所指类型字节数)。节数)。pi1与与pi2必须指向相同数据类型。必须指向相同数据类型。+:地址变量(:地址变量(pi)+ 或者或者 +地址变量(地址变量(pi),),结果为

21、在结果为在pi地址值位置跳过地址值位置跳过pi所指类型字节数个所指类型字节数个字节后的地址。分前字节后的地址。分前+和后和后+。-:地址变量(:地址变量(pi)- 或者或者 -地址变量(地址变量(pi),结果),结果为在为在pi地址值位置跳回地址值位置跳回pi所指类型字节数个字节所指类型字节数个字节后的地址。分前后的地址。分前-和后和后-。2021/6/1624C程序设计快速进阶大学教程2024/8/242511.3.1 一维数组与指针一维数组与指针1. 指针相关的运算符指针相关的运算符(5) 关系运算。支持关系运算。支持6种关系运算符,用来比较地址种关系运算符,用来比较地址的大小。例如:的大

22、小。例如:&iArr1 &iArr3 为真;为真;piiArr+3为真(为真(pi的值为的值为iArr)。)。2021/6/1625C程序设计快速进阶大学教程2024/8/242611.3.1 一维数组与指针一维数组与指针1. 指针相关的运算符指针相关的运算符(5) 关系运算。关系运算。int iArr5=0,1,2,3,4; int *pi,*pi1,*pi2; pi=&iArr1; pi1=&iArr2; pi2=&iArr4;*pi+:由于:由于+和和*同优先级,结合方向自右而左,等价于同优先级,结合方向自右而左,等价于*(pi+)。先对。先对*pi,然后,然后pi加加1。表达式的值为。

23、表达式的值为iArr1,pi的值为的值为&iArr2。*+pi:等价于:等价于*(+pi)。先。先pi加加1,然后,然后*pi。表达式的值为。表达式的值为iArr2,pi的的值为值为&iArr2。 (*pi)+:先:先*pi,然后(,然后(*pi)加)加1。表达式的值为。表达式的值为iArr1+,iArr1的的值改变了,值改变了,pi的值为的值为&iArr1,pi的值未改变。的值未改变。 pi2-pi1:pi2和和pi1相差两个整型数所占字节数的大小,它的返回值不是相相差两个整型数所占字节数的大小,它的返回值不是相差字节数,而是相差整数的个数,所以值为差字节数,而是相差整数的个数,所以值为2。

24、 上述算术运算符对简单变量地址运算是无意义的,因为对于一个简单变量上述算术运算符对简单变量地址运算是无意义的,因为对于一个简单变量x,&x+5计算的结果地址不知道是哪个数据的地址。而数组空间是连续计算的结果地址不知道是哪个数据的地址。而数组空间是连续的,对于一个数组的,对于一个数组arr,arr+5就是就是arr5的地址。的地址。 2021/6/1626C程序设计快速进阶大学教程2024/8/242711.3.1 一维数组与指针一维数组与指针1. 指针相关的运算符指针相关的运算符(5) 关系运算。关系运算。int iArr5=0,1,2,3,4; int *pi,*pi1,*pi2; pi=&

25、iArr1; pi1=&iArr2; pi2=&iArr4;*pi+:由于:由于+和和*同优先级,结合方向自右而左,等价于同优先级,结合方向自右而左,等价于*(pi+)。先对。先对*pi,然后,然后pi加加1。表达式的值为。表达式的值为iArr1,pi的值为的值为&iArr2。*+pi:等价于:等价于*(+pi)。先。先pi加加1,然后,然后*pi。表达式的值为。表达式的值为iArr2,pi的的值为值为&iArr2。 (*pi)+:先:先*pi,然后(,然后(*pi)加)加1。表达式的值为。表达式的值为iArr1+,iArr1的的值改变了,值改变了,pi的值为的值为&iArr1,pi的值未改变

26、。的值未改变。 pi2-pi1:pi2和和pi1相差两个整型数所占字节数的大小,它的返回值不是相相差两个整型数所占字节数的大小,它的返回值不是相差字节数,而是相差整数的个数,所以值为差字节数,而是相差整数的个数,所以值为2。 上述算术运算符对简单变量地址运算是无意义的,因为对于一个简单变量上述算术运算符对简单变量地址运算是无意义的,因为对于一个简单变量x,&x+5计算的结果地址不知道是哪个数据的地址。而数组空间是连续计算的结果地址不知道是哪个数据的地址。而数组空间是连续的,对于一个数组的,对于一个数组arr,arr+5就是就是arr5的地址。的地址。 2021/6/1627C程序设计快速进阶大

27、学教程2024/8/242811.3.1 一维数组与指针一维数组与指针2.引用数组元素引用数组元素 int iArr5=1,2,3,4,5; int *pi; pi=iArr;(1) pi+i1和和iArr+i1就是就是iArri1的地址,或者说它们指向的地址,或者说它们指向iArr数组的第数组的第i个元素。个元素。(2) *(pi+i1)或或*( iArr+i1)就是就是pi+i1或或iArr+i1所指向的数组所指向的数组元素,即元素,即iArr i1。例如,。例如,*(pi+2)或或*(iArr+2)就是就是iArr2。(3) 指向数组指针变量可以带下标,如指向数组指针变量可以带下标,如p

28、ii1与与*(pi+i1)等价。等价。引入指针变量后,对于数组引入指针变量后,对于数组iArr,pi是指向数组的指针变量,是指向数组的指针变量,其初值其初值pi=iArr。就可以用两种方法来访问数组元素。就可以用两种方法来访问数组元素:(1) 下标法,即用下标法,即用iArri1形式访问数组元素,也可以用形式访问数组元素,也可以用pii1访问数组元素。访问数组元素。(2) 指针法,即采用指针法,即采用*(iArr+i1)或或*(pi+i1)形式,用间接访形式,用间接访问的方法来访问数组元素。问的方法来访问数组元素。2021/6/1628C程序设计快速进阶大学教程2024/8/242911.3.

29、1 一维数组与指针一维数组与指针例例11.3 数组元素赋值并输出(数组名下标法)数组元素赋值并输出(数组名下标法)#include int main() int iArr5,i1; for(i1=0;i15;i1+) iArri1=i1; for(i1=0;i15;i1+) printf(iArr%d=%dn,i1,iArri1); return 0;2021/6/1629C程序设计快速进阶大学教程2024/8/243011.3.1 一维数组与指针一维数组与指针例例11.4 数组元素赋值并输出(指针变量下标法)数组元素赋值并输出(指针变量下标法)#include int main() int

30、iArr5,i1; int *pi=iArr; /*pi为变量,为变量,iArr为常量为常量*/ for(i1=0;i15;i1+) pii1=i1; for(i1=0;i15;i1+) printf(iArr%d=%dn,i1,pii1); return 0;2021/6/1630C程序设计快速进阶大学教程2024/8/243111.3.1 一维数组与指针一维数组与指针例例11.5 数组元素赋值并输出(数组名指针法)数组元素赋值并输出(数组名指针法)#include int main() int iArr5,i1; for(i1=0;i15;i1+) *(iArr+i1)=i1; for(i

31、1=0;i15;i1+) printf(iArr%d=%dn,i1,*(iArr+i1); return 0;2021/6/1631C程序设计快速进阶大学教程2024/8/243211.3.1 一维数组与指针一维数组与指针例例11.6 数组元素赋值并输出(指针变量指针法)数组元素赋值并输出(指针变量指针法)#include int main() int iArr5,i1; int *pi=iArr; for(i1=0;i15;i1+) *(pi+i1)=i1; for(i1=0;i15;i1+) printf(iArr%d=%dn,i1,*(pi+i1); return 0;2021/6/16

32、32C程序设计快速进阶大学教程2024/8/243311.3.1 一维数组与指针一维数组与指针例例11.7 数组元素赋值并输出(指针变量指针移动法)数组元素赋值并输出(指针变量指针移动法)#include int main() int iArr5,i1; int *pi=iArr; for(i1=0;i15;i1+) *pi=i1;pi+; /*此时,此时,pi已经指向已经指向iArr4之后,输出数组元素,之后,输出数组元素,pi重新指回数组头部重新指回数组头部*/ pi=iArr; for(i1=0;i15;i1+) printf(iArr%d=%dn,i1,*pi);pi+; return

33、 0;2021/6/1633C程序设计快速进阶大学教程2024/8/243411.3.1 一维数组与指针一维数组与指针例例11.8 数组元素赋值并输出(指针变量关系运算指针法)数组元素赋值并输出(指针变量关系运算指针法)#include int main() int iArr5,i1=0; int *pi=iArr; for(;piiArr+5;pi+,i1+)*pi=i1; /*此时,此时,pi已经指向已经指向iArr4之后,之后,为下面输出数组,必须让为下面输出数组,必须让pi重新指回数组头部重新指回数组头部*/ pi=iArr;i1=0; for(;piiArr+5;pi+,i1+) p

34、rintf(iArr%d=%dn,i1,*pi); return 0;2021/6/1634C程序设计快速进阶大学教程2024/8/243511.3.2 二维数组与指针二维数组与指针1. 理解二维数组理解二维数组 C语言对二维数组的存储是行优先方式的,对于整语言对二维数组的存储是行优先方式的,对于整型二维数组型二维数组iArr。int iArr34=1,2,3,4,5,6,7,8,9,10,11,122021/6/1635C程序设计快速进阶大学教程2024/8/243611.3.2 二维数组与指针二维数组与指针1. 理解二维数组理解二维数组一一个个二二维维数数组组是是以以一一维维数数组组为为元

35、元素素构构造造的的一一维维数数组组,也也就就是是二二维维数数组组可可以以看看作作一一维维数数组组,只只不不过过该该一一维维数数组组的的每每个个元元素素又又是是一一个个一一维维数数组组。如如iArr,把把iArr当当作作一一维维数数组组看看待待,iArr有有3个个元元素素,分分别别为为iArr0,iArr1,iArr2,每每个个元元素是一个有素是一个有4个整型元素构成的一维数组。个整型元素构成的一维数组。2021/6/1636C程序设计快速进阶大学教程2024/8/243711.3.2 二维数组与指针二维数组与指针1. 理解二维数组理解二维数组iArri1有有两两层层含含义义,它它既既是是“一一

36、维维数数组组iArr”的的数数组组元素,又是一维数组名。元素,又是一维数组名。iArr1是数组是数组iArr的一个数组元素;的一个数组元素;同同时时,iArr1是是一一个个一一维维数数组组名名,含含有有iArr10,iArr11,iArr12,iArr13四个元素。四个元素。2021/6/1637C程序设计快速进阶大学教程2024/8/243811.3.2 二维数组与指针二维数组与指针1. 理解二维数组(对比一维)理解二维数组(对比一维)对于一维数组:对于一维数组:int iArr14=11,12,13,14;iArr1是一个其数组元素类型的常量地址,即是一个其数组元素类型的常量地址,即int

37、型的型的常量地址常量地址,则,则iArr1+1的值会跳过一个数组元素,的值会跳过一个数组元素,即跳过即跳过4个字节(假定一个个字节(假定一个int,4个字节)。个字节)。对于当作一维数组的对于当作一维数组的“iArr”,iArr是一个其数组元是一个其数组元素类型的常量地址,它的数组元素为素类型的常量地址,它的数组元素为iArri1(iArri1为为4个个int类型的一维数组),类型的一维数组),所所以以iArr为大小为为大小为4的一维整型数组型的常量地址的一维整型数组型的常量地址,则则iArr+1的值会跳过一个数组元素,即跳过大小的值会跳过一个数组元素,即跳过大小为为4的一维整型数组(一行,的

38、一维整型数组(一行,16个字节,假定一个个字节,假定一个int为为4个字节)。因此也把个字节)。因此也把iArr称为称为行地址行地址。2021/6/1638C程序设计快速进阶大学教程2024/8/243911.3.2 二维数组与指针二维数组与指针1. 理解二维数组(对比一维)理解二维数组(对比一维)在在一一维维数数组组中中iArr1中中,iArr1i1等等价价于于*( iArr1+i1),代代表表取取出出第第i1个个元元素素。在在二二维维数数组组iArr中中,iArri1也也 等等 价价 于于 *(iArr+i1), iArri1和和 *( iArr+i1)是是一一维维数数组组的的数数组组名名

39、和和首首地地址址。因因为为iArri1和和*(iArr+i1)为为一一维维数数组组,为为整整数数类类型型常常量量地地址址,所所以以iArri1+1和和*(iArr+i1)+1都都会会跳跳过过一一个个整整型型数数据据(一一列列,4个个字字节节,假假定定一一个个int为为4个个字字节节),因因此此,也也把把iArri1和和*(iArr+i1)称称为为列地址列地址。2021/6/1639C程序设计快速进阶大学教程2024/8/244011.3.2 二维数组与指针二维数组与指针1. 理解二维数组(对比一维)理解二维数组(对比一维)行地址(一维数组地址),一次跳过一行,如行地址(一维数组地址),一次跳过

40、一行,如iArr、iArr+i1、 &iArri1、&*(iArr+i1);列地址(数据元素),一次跳过一列,如列地址(数据元素),一次跳过一列,如 *iArr、*(iArr+i1)、iArri1。*(*(iArr+1)+2): iArr+1一行指针,*(iArr+1)一列指针,*(iArr+1)+2 一行二列地址,*(*(iArr+1)+2) 一行二列地址间接访问到iArr12,值为7。 2021/6/1640C程序设计快速进阶大学教程2024/8/244111.3.2 二维数组与指针二维数组与指针例例11.9 行列地址行列地址#include int main() int iArr34=1

41、,2,3,4,5,6,7,8,9,10,11,12; /*行地址行地址*/ printf(行地址行地址n); printf(iArr=%x , ,iArr); printf(iArr+1=%xn,iArr+1); printf(&iArr0=%x , ,&iArr0); printf(&iArr0+1=%xn,&iArr0+1); printf(&*(iArr+0)=%x , ,&*(iArr+0); printf(&*(iArr+0)+1=%xn,&*(iArr+0)+1); /*列地址列地址*/ printf(列地址列地址n); printf(*iArr=%x , ,*iArr); pri

42、ntf(*iArr+1=%xn,*iArr+1); printf(iArr0=%x , ,iArr0); printf(iArr0+1=%xn,iArr0+1); printf(*(iArr+0)=%x , ,*(iArr+0); printf(*(iArr+0)+1=%xn,*(iArr+0)+1);程序运行结果:程序运行结果:行地址行地址iArr=12ff50 , iArr+1=12ff60&iArr0=12ff50 , &iArr0+1=12ff60&*(iArr+0)=12ff50 , &*(iArr+0)+1=12ff60列地址列地址*iArr=12ff50 , *iArr+1=12

43、ff54iArr0=12ff50 , iArr0+1=12ff54*(iArr+0)=12ff50 , *(iArr+0)+1=12ff54数据元素数据元素iArr12=7 /*访问元素访问元素*/ printf(数据元素数据元素n); printf(iArr12=%dn,*(*(iArr+1)+2); return 0;2021/6/1641C程序设计快速进阶大学教程2024/8/244211.3.2 二维数组与指针二维数组与指针2.指向一维数组的指针指向一维数组的指针 对于一维数组对于一维数组int iArr14;可以把可以把iArr赋值给指向赋值给指向int型的指针变量。如:型的指针变量

44、。如:int *pi1; pi1=iArr1;对于二维数组对于二维数组int iArr34=1,2,3,4,5,6,7,8,9,10,11,12;同样可以把同样可以把iArr赋值给指向赋值给指向一维数组一维数组的指针变量,因为二维数的指针变量,因为二维数组的可以看成以一维数组为成员的一维数组。组的可以看成以一维数组为成员的一维数组。int (*pia)4;它表示它表示pia是一个指针变量,它指向包含是一个指针变量,它指向包含4个元素的一维数组。个元素的一维数组。然后就可以赋值:然后就可以赋值:pia=iArr;2021/6/1642C程序设计快速进阶大学教程2024/8/244311.3.2

45、二维数组与指针二维数组与指针2.指向一维数组的指针指向一维数组的指针 pia指向第一个一维数组指向第一个一维数组iArr0,其值等于,其值等于iArr。而。而pia+1则指向一维数组则指向一维数组iArr1。从前面的行列地址。从前面的行列地址分析可得出分析可得出*(pia+iRow)+iCol是二维数组是二维数组iRow行行iCol 列的元素的地址,而列的元素的地址,而*(*(pia+iRow)+iCol)则则是是iRow行行iCol列元素的值。列元素的值。2021/6/1643C程序设计快速进阶大学教程2024/8/244411.3.2 二维数组与指针二维数组与指针2.指向一维数组的指针指向

46、一维数组的指针 指向一维数组的指针变量定义的一般形式为:指向一维数组的指针变量定义的一般形式为: 类型说明符类型说明符 (*指针变量名指针变量名)数组长度数组长度;其中其中“类型说明符类型说明符”为所指数组的数组元素类型,为所指数组的数组元素类型,“*”表示其后的变量是指针类型,表示其后的变量是指针类型,“数组长度数组长度”表示所指向一维数组的长度。应注意表示所指向一维数组的长度。应注意“(*指针变指针变量名量名)”两边的括号不可少,如缺少括号则表示是两边的括号不可少,如缺少括号则表示是指针数组指针数组(后面介绍后面介绍),意义就完全不同了。,意义就完全不同了。可以这样理解:先看小括号内,有可

47、以这样理解:先看小括号内,有*号是在定义指针号是在定义指针变量;然后是中括号,表示指针变量指向该长度变量;然后是中括号,表示指针变量指向该长度的一维数组;最后看类型说明符,表示该数组的的一维数组;最后看类型说明符,表示该数组的每个元素为类型说明符说明的类型。每个元素为类型说明符说明的类型。2021/6/1644C程序设计快速进阶大学教程2024/8/244511.3.2 二维数组与指针二维数组与指针例例11.10 一个学习小组有一个学习小组有5个人,每个人有个人,每个人有3门课的考试成绩。要求利用函数门课的考试成绩。要求利用函数计算每门课程的平均成绩计算每门课程的平均成绩如:如: 赵赵钱钱 孙

48、孙李李张张Math 80 61598576C 7565638777English 9271709085问题分析:问题分析:可定义一个二维数组可定义一个二维数组score35存储五个人存储五个人3门课的成绩。再定义一个一维门课的成绩。再定义一个一维数组数组courseAverage3存储计算所得各门课平均成绩。存储计算所得各门课平均成绩。要完成的要接收一门课程(数组的一行)为参数,所以应该设指向一维数要完成的要接收一门课程(数组的一行)为参数,所以应该设指向一维数组的指针为参数。组的指针为参数。算法描述:算法描述:1. 依次输入每门课程的成绩(每门课一行)。依次输入每门课程的成绩(每门课一行)。

49、2. 计算每门课程平均成绩,即对每行计算平均成绩(函数完成)。计算每门课程平均成绩,即对每行计算平均成绩(函数完成)。3. 输出每门课程平均成绩。输出每门课程平均成绩。2021/6/1645C程序设计快速进阶大学教程2024/8/244611.3.2 二维数组与指针二维数组与指针#include int main() int i,j; float sum; float score35; /*存储成绩存储成绩*/ float courseAverage3;/*存储每门课程平均成绩存储每门课程平均成绩*/ float average(float (*p)5); /*输入成绩输入成绩*/ for(i

50、=0;i3;i+) /*行(每门课)循环行(每门课)循环*/ for(j=0;j5;j+) /*行内每列循环行内每列循环*/ scanf(%f,&scoreij); /*输出成绩表输出成绩表*/ for(i=0;i3;i+) /*行(每门课)循环行(每门课)循环*/ for(j=0;j5;j+) /*行内每列循环行内每列循环*/ printf(%ft,scoreij); printf(n); /*每行结束输出一个换行每行结束输出一个换行*/ /*计算平均成绩计算平均成绩*/ for(i=0;i3;i+) /*行(每门课)循环行(每门课)循环*/ courseAveragei=average(s

51、core+i);/*每行地址为参数每行地址为参数*/ /*输出成绩表输出成绩表*/ for(i=0;i3;i+) printf(%ft,courseAveragei); return 0;/*计算平均成绩,参数为行地址计算平均成绩,参数为行地址(指向一维数组指针)(指向一维数组指针)*/float average(float (*p)5) int i; float sum=0; for(i=0;i5;i+) /* *p转为列地址,转为列地址,(*p+i)偏移偏移i,间接访问间接访问*(*p+i) */sum+=*(*p+i); return sum/5;2021/6/1646C程序设计快速进阶

52、大学教程2024/8/244711.3.3 指针数组指针数组一个数组的元素值为指针,则该数组称为一个数组的元素值为指针,则该数组称为指针数组指针数组。指针数组所有元素都必须是指向相同数据类型的指针。指针数组所有元素都必须是指向相同数据类型的指针。指针数组定义的一般形式为:指针数组定义的一般形式为: 类型说明符类型说明符 *数组名数组名数组长度数组长度;可以这样理解:先看可以这样理解:先看“数组名数组名数组长度数组长度”,表示定义,表示定义一个该长度的一维数组;然后看一个该长度的一维数组;然后看“类型说明符类型说明符 *”,表示该数组的每个元素为指向该类型说明符,表示该数组的每个元素为指向该类型

53、说明符类型的指针。类型的指针。例如:例如:int *pa3;表示表示pa是一个指针数组,它有三个数组元素,每个元是一个指针数组,它有三个数组元素,每个元素值都是一个指针,指向整型变量。素值都是一个指针,指向整型变量。2021/6/1647C程序设计快速进阶大学教程2024/8/244811.3.3 指针数组指针数组例例11.11 通过指针数组访问二维数组通过指针数组访问二维数组#include int main() int iArr34=1,2,3,4,5,6,7,8,9,10,11,12; int *pa3;/*指针数组,每个成员都是指向指针数组,每个成员都是指向int型的指针型的指针*/

54、int iRow; pa0=iArr0; /*iArr0为一维数组名,为为一维数组名,为int型地址型地址*/ pa1=iArr1; pa2=iArr2; for(iRow=0;iRow3;iRow+) printf(%d,%d,%d,%dn,*paiRow,*(paiRow+1), *(paiRow+2),*(paiRow+3); return 0;程序运行结果:程序运行结果:1,2,3,45,67,89,10,11,12 2021/6/1648C程序设计快速进阶大学教程2024/8/244911.3.3 指针数组指针数组例例11.11 通过指针数组访问二维数组通过指针数组访问二维数组202

55、1/6/1649C程序设计快速进阶大学教程2024/8/245011.3.4 指向指针的指针指向指针的指针 对一维数组对一维数组int iArr15;数组成员类型是数组成员类型是int,一维数组名,一维数组名iArr1是指向是指向int的指的指针常量,是指向其成员类型的指针常量。针常量,是指向其成员类型的指针常量。对于指针数组对于指针数组int *pa3;数组成员类型是数组成员类型是int *,一维数组名,一维数组名pa是指向是指向int *的指的指针常量,同样是指向其成员类型(指向整形的指针常量,同样是指向其成员类型(指向整形的指针)的指针常量,也就是说针)的指针常量,也就是说pa是是指向指

56、向指向整型指指向整型指针针的指针的指针。2021/6/1650C程序设计快速进阶大学教程2024/8/245111.3.4 指向指针的指针指向指针的指针 指向指针的指针定义的一般形式为:指向指针的指针定义的一般形式为:类型说明符类型说明符 *变量名变量名;可以这样理解:先看可以这样理解:先看“*变量名变量名”,表示定义一个指,表示定义一个指针变量;然后看针变量;然后看“类型说明符类型说明符 *”,表示该指针变,表示该指针变量为指向量为指向“类型说明符类型说明符 *”类型的指针。类型的指针。char c1=A;char *pc;char *ppc;pc=&c1;ppc=&pc; c1、*pc、*

57、ppc的值都为的值都为A;分别为直接访问、间接访问、二级间接访问分别为直接访问、间接访问、二级间接访问2021/6/1651C程序设计快速进阶大学教程2024/8/245211.3.4 指向指针的指针指向指针的指针 例例11.12 不移动数据,通过改变指针使得不移动数据,通过改变指针使得追加数据有序追加数据有序#include int main() int iArr5=1,5,7,9; int *pa5=&iArr0,&iArr1,&iArr2,&iArr3,0; int *ppi,i1; /*-输出原来输出原来4个有序数据个有序数据-*/ printf(输出原来输出原来4个有序数据个有序数据

58、n); ppi=pa;/*ppi和和pa同样为指向整型的指针的指针同样为指向整型的指针的指针 */ for(i1=0;i14;i1+) printf(%dn,*ppi); ppi+; /*-追加一个数据,原来数据不动,追加一个数据,原来数据不动,调整指针数组,通过指针数组访问调整指针数组,通过指针数组访问仍然有序仍然有序-*/ iArr4=3; pa1=&iArr4; pa2=&iArr1; pa3=&iArr2; pa4=&iArr3; /*-输出追加输出追加1个之后的个之后的5个有序数据个有序数据-*/ ppi=pa;/*指针回到前面指针回到前面*/ printf(输出追加之后输出追加之后

59、5个有序数据个有序数据n); for(i1=0;i15;i1+) printf(%dn,*ppi);ppi+; return 0;程序运行结果:程序运行结果:输出原来输出原来4个有序数据个有序数据1579输出追加输出追加1个之后的个之后的5个有序数据个有序数据135792021/6/1652C程序设计快速进阶大学教程2024/8/245311.3.4 指向指针的指针指向指针的指针 2021/6/1653课堂练习课堂练习1.指针类型作用?指针类型作用?2指针与下标?指针与下标?3.不用指针可以吗?不用指针可以吗?4.用指针方法实现一个一维数组的转置。用指针方法实现一个一维数组的转置。C程序设计快

60、速进阶大学教程2024/8/24542021/6/1654C程序设计快速进阶大学教程2024/8/245511.4.1 指针作函数参数指针作函数参数 例例11.13 交换变量数据交换变量数据交换形参指针变量交换形参指针变量#include void swap(int *pi1Copy,int *pi2Copy) int *piTemp; piTemp=pi1Copy; pi1Copy=pi2Copy; pi2Copy=piTemp;int main() int i1=3,i2=4; int *pi1,*pi2; pi1=&i1; pi2=&i2; swap(pi1,pi2); printf(i

61、1=%dni2=%dn,i1,i2); return 0; 2021/6/1655C程序设计快速进阶大学教程2024/8/245611.4.1 指针作函数参数指针作函数参数 例例11.13 交换变量数据交换变量数据交换形参指针变量交换形参指针变量2021/6/1656C程序设计快速进阶大学教程2024/8/245711.4.1 指针作函数参数指针作函数参数 例例11.14 交换形参指针变量所指向的变量交换形参指针变量所指向的变量#include void swap(int *pi1Copy,int *pi2Copy) int iTemp=0; /*交换形参指针变量所指向的变量,交换形参指针变量

62、所指向的变量, 实参不受影响,但是实参所指向实参不受影响,但是实参所指向 数据改变了数据改变了*/ iTemp=*pi1Copy; /*用的间接访问,实际上是访问用的间接访问,实际上是访问i1、i2*/ *pi1Copy=*pi2Copy; *pi2Copy=iTemp;int main() int i1=3,i2=4; int *pi1,*pi2; pi1=&i1; pi2=&i2; swap(pi1,pi2); printf(i1=%dni2=%dn, i1,i2); return 0;2021/6/1657C程序设计快速进阶大学教程2024/8/245811.4.1 指针作函数参数指针作

63、函数参数 例例11.14 交换形参指针变量所指向的变量交换形参指针变量所指向的变量2021/6/1658C程序设计快速进阶大学教程2024/8/245911.4.1 指针作函数参数指针作函数参数 例例11.14 交换形参指针变量所指向的变量交换形参指针变量所指向的变量若把若把swap函数改成下面的写法:函数改成下面的写法:void swap(int *pi1Copy,int *pi2Copy) int *ipTemp; *ipTemp=*pi1Copy; /* ipTemp指向哪里?指向哪里? */ *pi1Copy=*pi2Copy; *pi2Copy=*ipTemp;2021/6/1659

64、C程序设计快速进阶大学教程2024/8/246011.4.2 指针作函数参数指针作函数参数 例例11.16 对数组中的每个元素加对数组中的每个元素加1#include int main() int iArr13=2,5,3,iJ; void add(int iArr23); /*输出数组输出数组*/ for(iJ=0;iJ=2;iJ+)printf(%d ,iArr1iJ); printf(n); add(iArr1);/*数组名作为实参,注意,只有数组名,没有下标数组名作为实参,注意,只有数组名,没有下标*/ /*函数调用后,输出数组函数调用后,输出数组*/ for(iJ=0;iJ=2;iJ

65、+)printf(%d ,iArr1iJ); printf(n); return 0;void add(int iArr23) int iI; for(iI=0;iI=2;iI+) iArr2iI+;2021/6/1660C程序设计快速进阶大学教程2024/8/246111.4.2 数组名作函数参数数组名作函数参数 指针变量地址,所以实参数组与形参数组可以用指针变量取代指针变量地址,所以实参数组与形参数组可以用指针变量取代pi=iArr1;add(pi);/*指针变量作为实参指针变量作为实参*/void add(int* iArr2) /*指针变量作形参指针变量作形参*/还可以实参用数组名,形

66、参用变量名,如:还可以实参用数组名,形参用变量名,如:add(iArr1);/*数组名作为实参数组名作为实参*/void add(int* iArr2) /*指针变量作形参指针变量作形参*/也可以用指针变量作实参,数组名作为形参,如:也可以用指针变量作实参,数组名作为形参,如:pi=iArr1;add(pi);/*指针变量作为实参指针变量作为实参*/void add(int iArr23) /*数组名作为形参数组名作为形参*/2021/6/1661C程序设计快速进阶大学教程2024/8/246211.4.2 数组名作函数参数数组名作函数参数 归纳起来,如果有一个实参数组,想在函数中改归纳起来,

67、如果有一个实参数组,想在函数中改变此数组的元素的值,实参与形参的对应关系有以变此数组的元素的值,实参与形参的对应关系有以下种:下种:(1) 形参和实参都是数组名。形参和实参都是数组名。(2) 实参用数组,形参用指针变量。实参用数组,形参用指针变量。(3) 实参、形参都用指针变量。实参、形参都用指针变量。(4) 实参为指针变量,形参为数组名。实参为指针变量,形参为数组名。通常情况下,为了能够让函数处理不同长度的数组,可以通常情况下,为了能够让函数处理不同长度的数组,可以在参数中增加一处理数据长度的形参变量。还有函数的返在参数中增加一处理数据长度的形参变量。还有函数的返回值只有一个,若需要函数返回

68、多个同类型结果数据,也回值只有一个,若需要函数返回多个同类型结果数据,也可以利用数组作函数参数,见例可以利用数组作函数参数,见例11.20。2021/6/1662C程序设计快速进阶大学教程2024/8/246311.4.2 数组名作函数参数数组名作函数参数 归纳起来,如果有一个实参数组,想在函数中改归纳起来,如果有一个实参数组,想在函数中改变此数组的元素的值,实参与形参的对应关系有以变此数组的元素的值,实参与形参的对应关系有以下种:下种:(1) 形参和实参都是数组名。形参和实参都是数组名。(2) 实参用数组,形参用指针变量。实参用数组,形参用指针变量。(3) 实参、形参都用指针变量。实参、形参

69、都用指针变量。(4) 实参为指针变量,形参为数组名。实参为指针变量,形参为数组名。通常情况下,为了能够让函数处理不同长度的数组,可以通常情况下,为了能够让函数处理不同长度的数组,可以在参数中增加一处理数据长度的形参变量。还有函数的返在参数中增加一处理数据长度的形参变量。还有函数的返回值只有一个,若需要函数返回多个同类型结果数据,也回值只有一个,若需要函数返回多个同类型结果数据,也可以利用数组作函数参数,见例可以利用数组作函数参数,见例11.20。2021/6/1663C程序设计快速进阶大学教程2024/8/246411.4.2 指针作函数参数指针作函数参数 例例11.20 把给定整数数组中能被

70、把给定整数数组中能被3整除的数据挑出来整除的数据挑出来#include int select(int *piSourceCopy,int iN,int *piTargetCopy) int i1,iNum=0; for(i1=0;i1iN;i1+) if(piSourceCopyi1%3=0) piTargetCopyiNum+=piSourceCopyi1; return iNum;int main() int iArrSource10=5,15,25,36,47,58,69,78,56,90; int iArrTarget10;/*存放结果存放结果*/ int i1,iNum=0; iNu

71、m=select(iArrSource,10,iArrTarget); for(i1=0;i1iNum;i1+) printf(%d ,iArrTargeti1); return 0;2021/6/1664C程序设计快速进阶大学教程2024/8/246511.4.3 返回指针值的函数返回指针值的函数 在语言中允许一个函数的返回值是一个指针在语言中允许一个函数的返回值是一个指针(即地址即地址),这种返回指,这种返回指针值的函数称为指针型函数。针值的函数称为指针型函数。定义指针型函数的一般形式为:定义指针型函数的一般形式为:类型说明符类型说明符 * 函数名函数名(形参表形参表) /*函数体函数体*

72、/ 把把“类型说明符类型说明符 *”放在一起理解,则表示函数的返回值为指向放在一起理解,则表示函数的返回值为指向“类类型说明符型说明符”类型的指针。例如:类型的指针。例如: int *f(int x,int y) . /*函数体函数体*/ 表示表示f是一个返回指针值的函数,它返回指向一个整型变量的指针。是一个返回指针值的函数,它返回指向一个整型变量的指针。2021/6/1665C程序设计快速进阶大学教程2024/8/246611.4.3 返回指针值的函数返回指针值的函数 例例11.18 在给定整数数组中选出最大整数并返回其地址在给定整数数组中选出最大整数并返回其地址#include int *

73、max(int *piSourceCopy,int iN)/*返回指针返回指针*/ int i1; int *pi1=&piSourceCopy0;/*记载最大元素地址记载最大元素地址*/ for(i1=1;i1*pi1) pi1=&piSourceCopyi1; return pi1;int main() int iArrSource10=5,15,25,36,47,58,69,78,56,90; int *pi;/*接收最大元素地址接收最大元素地址*/ pi=max(iArrSource,10); printf(%d,*pi); return 0;2021/6/1666C程序设计快速进阶大

74、学教程2024/8/246711.4.3 返回指针值的函数返回指针值的函数 例例11.19指向已经释放数据空间指向已经释放数据空间#include char * lost() char c1=A; return &c1;int main() char *pc; pc=lost(); printf(%c,*pc); return 0;2021/6/1667C程序设计快速进阶大学教程2024/8/246811.4.4 指向函数的指针指向函数的指针 在语言中,一个函数总是占用一段连续的内存区,在语言中,一个函数总是占用一段连续的内存区,而函数名就是该函数所占内存区的首地址。我们而函数名就是该函数所占

75、内存区的首地址。我们可以把函数的这个首地址可以把函数的这个首地址(或称入口地址或称入口地址)赋予一赋予一个指针变量,使该指针变量指向该函数。然后通个指针变量,使该指针变量指向该函数。然后通过指针变量就可以找到并调用这个函数。我们把过指针变量就可以找到并调用这个函数。我们把这种指向函数的指针变量称为这种指向函数的指针变量称为“函数指针变量函数指针变量”。函数指针变量定义的一般形式为:函数指针变量定义的一般形式为: 类型说明符类型说明符 (*指针变量名指针变量名)(参数表参数表); 首先首先“(*指针变量名指针变量名)”,说明是在定义指针,说明是在定义指针变量;其次变量;其次“(参数表)(参数表)

76、”,说明指针指向函数;,说明指针指向函数;最后最后“类型说明符类型说明符”,表示被指函数的返回值的,表示被指函数的返回值的类型。类型。2021/6/1668C程序设计快速进阶大学教程2024/8/246911.4.4 指向函数的指针指向函数的指针 例例11.20 计算两个整数最大值通过函数指针调用函数计算两个整数最大值通过函数指针调用函数#includeint max(int i1,int i2) if(i1i2)return i1; elsereturn i2;int main() int(*pf)(int,int);/*定义函数指针定义函数指针*/ int i1,i2,i3; pf=max

77、;/* 函数名赋值给函数指针变量函数名赋值给函数指针变量 */ printf(input two numbers:n); scanf(%d%d,&i1,&i2); i3=(*pf)(i1,i2); /* 通过函数指针调用函数通过函数指针调用函数 */ printf(maxmum=%d,i3); return 0;2021/6/1669C程序设计快速进阶大学教程2024/8/247011.4.4 指向函数的指针指向函数的指针 函数指针变量形式调用函数的步骤如下:函数指针变量形式调用函数的步骤如下:(1) 先定义函数指针变量:先定义函数指针变量:int (*pf)(int,int);(2) 把被调

78、函数的入口地址把被调函数的入口地址(函数名函数名)赋予该函数指赋予该函数指针变量:针变量:pf=max;(3) 用函数指针变量形式调用函数:用函数指针变量形式调用函数:i3=(*pf)(i1,i2);使用函数指针变量还应注意以下两点:使用函数指针变量还应注意以下两点:(1) 函数指针变量不能进行算术运算,这是与数组函数指针变量不能进行算术运算,这是与数组指针变量不同的。指针变量不同的。(2) 函数调用中函数调用中(*指针变量名指针变量名)的两边的括号不可的两边的括号不可少。少。2021/6/1670课堂练习课堂练习 一个学习小组有一个学习小组有10个人,每个人学习个人,每个人学习3门课程,门课

79、程,用用10行行3列浮点型数组存储。编写函数计算每列浮点型数组存储。编写函数计算每个人的总成绩,参数为个人的总成绩,参数为flaot (*p)3类型。类型。C程序设计快速进阶大学教程2024/8/24712021/6/1671C程序设计快速进阶大学教程2024/8/247211.5 字符串字符串 字符串常量是由一对双引号括起的字符序列。字符串常量是由一对双引号括起的字符序列。例如:例如:C Language、student、123等都是合等都是合法的字符串常量。法的字符串常量。字符串常量和字符常量是不同的。它们主要区别:字符串常量和字符常量是不同的。它们主要区别:(1) 字符常量由单引号括起来

80、,字符串常量由双引字符常量由单引号括起来,字符串常量由双引号括起来。号括起来。(2) 字符常量只能是单个字符,字符串常量则可以字符常量只能是单个字符,字符串常量则可以含零个或多个字符。含零个或多个字符。(3) 可以把一个字符常量赋予一个字符变量,但不可以把一个字符常量赋予一个字符变量,但不能把一个字符串常量赋予一个字符变量。在语能把一个字符串常量赋予一个字符变量。在语言中没有相应的字符串变量,但是可以用一个字言中没有相应的字符串变量,但是可以用一个字符数组来存放一个字符串常量。符数组来存放一个字符串常量。2021/6/1672C程序设计快速进阶大学教程2024/8/247311.5 字符串字符

81、串 (4) 字符常量占一个字节的内存空间。字符串不像字符常量占一个字节的内存空间。字符串不像其他其它数据类型具有固定的长度,不同字符串其他其它数据类型具有固定的长度,不同字符串是不等长的,因此,字符串的存储不光需要存储是不等长的,因此,字符串的存储不光需要存储其起始位置,还应该记载其结束位置。字符串常其起始位置,还应该记载其结束位置。字符串常量占的内存字节数等于字符串中字节数加量占的内存字节数等于字符串中字节数加1,增加,增加的一个字节中存放字符的一个字节中存放字符0 (ASCII码为码为0),这是字,这是字符串结束的标志。例如:符串结束的标志。例如:字符串字符串 “C Language”在内

82、存中所占的字节(在内存中所占的字节(11)2021/6/1673C程序设计快速进阶大学教程2024/8/247411.5.1 字符数组与字符串字符数组与字符串 在语言中没有专门的字符串变量,通常用在语言中没有专门的字符串变量,通常用一个字符数组来存放一个字符串。字符串是以一个字符数组来存放一个字符串。字符串是以0作为串的结束符。因此当把一个字符串存入一个作为串的结束符。因此当把一个字符串存入一个数组时,也把结束符数组时,也把结束符0存入数组,并以此作为该存入数组,并以此作为该字符串是否结束的标志。有了字符串是否结束的标志。有了0标志后,就不必标志后,就不必再用字符数组的长度来判断字符串的长度了

83、。再用字符数组的长度来判断字符串的长度了。2021/6/1674C程序设计快速进阶大学教程2024/8/247511.5.1 字符数组与字符串字符数组与字符串 语言允许用字符串的方式对数组作初始化赋值,但语言允许用字符串的方式对数组作初始化赋值,但是,与用字符初始化是有区别的。是,与用字符初始化是有区别的。char cArr=C, ,l,a,n,g,u,a,g,e;数组数组cArr大小为大小为10。可写利用字符串初始化为:可写利用字符串初始化为:char cArr=C Language;或去掉或去掉写为:写为:char cArr=C Language;数组数组cArr大小为大小为11。用字符串

84、方式赋值比用字符逐个用字符串方式赋值比用字符逐个赋值要多占一个字节,赋值要多占一个字节, 用于存放字符串结束标志用于存放字符串结束标志0。0是由是由C编译系统自动加上的。编译系统自动加上的。2021/6/1675C程序设计快速进阶大学教程2024/8/247611.5.1 字符数组与字符串字符数组与字符串 对于字符数组可以有两种使用方式:对于字符数组可以有两种使用方式:(1) 当作单个字符看待,如当作单个字符看待,如cArr0、Arr1;(2) 当作字符串看待,全体合在一起,代表一个含当作字符串看待,全体合在一起,代表一个含义,使用数组名。可以使用义,使用数组名。可以使用printf函数和函数

85、和scanf函函数一次性输出输入一个字符数组中的字符串,而数一次性输出输入一个字符数组中的字符串,而不必使用循环语句逐个地输入输出每个字符。不必使用循环语句逐个地输入输出每个字符。2021/6/1676C程序设计快速进阶大学教程2024/8/247711.5.1 字符数组与字符串字符数组与字符串 例例11.21 两种方式输出字符数组两种方式输出字符数组#includeint main() char cArr11=C Language;/*用字符串初始化用字符串初始化*/ int i1; /*按字符方式输出按字符方式输出*/ for(i1=0;i110;i1+) printf(%c,cArri1

86、); /*按字符串方式输出按字符串方式输出*/ printf(n%s,cArr);/* %s输出字符串,直接使用数组名输出字符串,直接使用数组名*/ return 0; 若改为若改为char cArr=C, ,l,a,n,g,u,a,g,e;2021/6/1677C程序设计快速进阶大学教程2024/8/247811.5.1 字符数组与字符串字符数组与字符串 例例11.22 两种方式输入字符数组两种方式输入字符数组#includeint main() char cArr111; char cArr211; int i1; /*按字符方式输入按字符方式输入*/ for(i1=0;i110;i1+)

87、 scanf(%c,&cArr1i1); /*按字符串方式输入按字符串方式输入*/ scanf(%s,cArr2);/* %s输入字符串,直接使用数组名输入字符串,直接使用数组名*/ return 0; (1) 由于定义数组长度为11,因此输入的字符串长度必须小于11,以留出一个字节用于存放字符串结束标志0;(2) scanf的各输入项必须以地址方式出现,而数组名恰好是数组空间的首地址,所以数组名前不能用&符号;(3) 当用scanf函数输入字符串时,字符串中不能含有空格,否则将以空格作为串的结束符。 2021/6/1678C程序设计快速进阶大学教程2024/8/247911.5. 2 字符串

88、与指针字符串与指针 在在C语言中,可以用字符数组存放一个字符串。如:语言中,可以用字符数组存放一个字符串。如:char cArr=C Language;cArr是数组名,它代表字符指向字符型的常量指针,是数组名,它代表字符指向字符型的常量指针,所以,字符数组名就可以赋值给指向字符型的指所以,字符数组名就可以赋值给指向字符型的指针变量。如:针变量。如:char *pc;pc=cArr;2021/6/1679C程序设计快速进阶大学教程2024/8/248011.5. 2 字符串与指针字符串与指针 例例11.23 通过指针变量访问字符数组通过指针变量访问字符数组#includeint main()

89、char cArr11=C Language;/*用字符串初始化用字符串初始化*/ int i1; char *pc; pc=cArr; printf(按字符方式输出按字符方式输出,下标方式:下标方式:n); for(i1=0;i110;i1+) printf(%c,pci1); printf(n按字符方式输出按字符方式输出,间接访问方式:间接访问方式:n); for(i1=0;i110;i1+,pc+) printf(%c,*pc); printf(n按字符串方式输出,每次起始位置后移:按字符串方式输出,每次起始位置后移:n); pc=cArr;/*因为之前因为之前pc已经移动已经移动*/

90、for(i1=0;i110;i1+,pc+) printf(%sn,pc);/* %s输出字符串,使用指针变量,每次指针后移输出字符串,使用指针变量,每次指针后移*/ return 0;程序运行结果:程序运行结果:按字符方式输出按字符方式输出,下标方式:下标方式:C Language按字符方式输出按字符方式输出,间接访问方式:间接访问方式:C Language按字符串方式输出按字符串方式输出,每次起始位置后移:每次起始位置后移:C Language LanguageLanguageanguagenguageguageuageagegee2021/6/1680C程序设计快速进阶大学教程2024/

91、8/248111.5. 2 字符串与指针字符串与指针 字符型指针变量还可以指向字符串常量。如:字符型指针变量还可以指向字符串常量。如: char *pc=C Language;表示表示pc是一个指向字符型的指针变量,把字符串的首是一个指向字符型的指针变量,把字符串的首地址赋予地址赋予pc。还可以写为:还可以写为:char *pc;pc=C Language;需要注意的是,字符型指针变量本身是一个变量,用需要注意的是,字符型指针变量本身是一个变量,用于存放字符串的首地址。而字符串常量本身是存于存放字符串的首地址。而字符串常量本身是存放在以该首地址为首的一块连续的内存空间中并放在以该首地址为首的一

92、块连续的内存空间中并以以0作为串的结束,字符串常量本身本身使不能作为串的结束,字符串常量本身本身使不能被更改的。被更改的。2021/6/1681C程序设计快速进阶大学教程2024/8/248211.5. 2 字符串与指针字符串与指针 对字符串存储,有用字符型指针变量指向字符串常量和按照字符数组存储对字符串存储,有用字符型指针变量指向字符串常量和按照字符数组存储两种方式,注意这两种方式的差异:两种方式,注意这两种方式的差异:(1)字符型指针变量指向字符串常量方式:)字符型指针变量指向字符串常量方式:char *pc=C Language;读取其中字符是允许的:读取其中字符是允许的:char c1

93、=pc3; /* 允许允许*/因为指向的是字符串常量,所以,写入是不允许的:因为指向的是字符串常量,所以,写入是不允许的:pc3= A; /* 不允许不允许*/更改字符型指针变量也是允许的:更改字符型指针变量也是允许的:pc=BASIC; /* 允许允许*/pc不再指向字符串常量不再指向字符串常量C Language,而是指向字符串常量,而是指向字符串常量BASIC。(2)字符数组方式:)字符数组方式:char cArr11= C Language;读写其中字符都是允许的:读写其中字符都是允许的:cahr c1=cArr3; cArr3= A; /* 都允许都允许*/数组名是不允许更改的:数组

94、名是不允许更改的:cArr=BASIC; /* 不允许不允许*/2021/6/1682C程序设计快速进阶大学教程2024/8/248311.5. 2 字符串与指针字符串与指针 2021/6/1683C程序设计快速进阶大学教程2024/8/248411.5. 3 字符串函数字符串函数 程序开发过程中经常涉及到字符串操作,尤其程序开发过程中经常涉及到字符串操作,尤其是管理性程序,如学生管理系统中的学号、银行是管理性程序,如学生管理系统中的学号、银行业务中帐号等。语言提供了丰富的字符串处理业务中帐号等。语言提供了丰富的字符串处理函数,大致可分为字符串的输入、输出、合并、函数,大致可分为字符串的输入、

95、输出、合并、修改、比较、转换、复制、搜索几类。使用这些修改、比较、转换、复制、搜索几类。使用这些函数可大大减轻编程的负担。用于输入输出的字函数可大大减轻编程的负担。用于输入输出的字符串函数,在使用前应包含头文件符串函数,在使用前应包含头文件stdio.h,使,使用其它字符串函数则应包含头文件用其它字符串函数则应包含头文件string.h。2021/6/1684C程序设计快速进阶大学教程2024/8/248511.5. 3 字符串函数字符串函数 1. 字符串输出函数字符串输出函数puts规格说明:规格说明:int puts(const char *pc);功能描述:把字符指针指定的字符串输出到标

96、准输出功能描述:把字符指针指定的字符串输出到标准输出流中,空字符不输出,但是输出一个换行符。流中,空字符不输出,但是输出一个换行符。函数参数:函数参数:pc可以使指针变量,也可以是字符数组名。可以使指针变量,也可以是字符数组名。函数返回值:若出现写错误,则返回函数返回值:若出现写错误,则返回EOF(-1),否),否则返回非负数。则返回非负数。例如:例如:char *pc=C Language;puts(pc);puts函数完全可以由函数完全可以由printf函数取代。当需要按一定函数取代。当需要按一定格式输出时,通常使用格式输出时,通常使用printf函数。函数。2021/6/1685C程序设

97、计快速进阶大学教程2024/8/248611.5. 3 字符串函数字符串函数 2. 字符串输入函数字符串输入函数gets规格说明:规格说明:char * gets(char *pc);功能描述:从标准输入流读字符到字符指针指定的字功能描述:从标准输入流读字符到字符指针指定的字符数组中,直到遇到换行符或输入文档结束符,符数组中,直到遇到换行符或输入文档结束符,并且丢弃换行符或结束符,然后在字符数组中添并且丢弃换行符或结束符,然后在字符数组中添加一个空字符。加一个空字符。函数参数:函数参数:pc必须是字符数组名或指向字符数组的指必须是字符数组名或指向字符数组的指针变量。不可以使用指针变量指向字符串

98、常量,针变量。不可以使用指针变量指向字符串常量,因为常量空间不允许改变。例如:因为常量空间不允许改变。例如:char *pc=C Language;gets(pc);内存写错误,试图向常量空间写入字符。内存写错误,试图向常量空间写入字符。2021/6/1686C程序设计快速进阶大学教程2024/8/248711.5. 3 字符串函数字符串函数 2. 字符串输入函数字符串输入函数gets规格说明:规格说明:char * gets(char *pc);函数返回值:若成功,返回函数返回值:若成功,返回pc1;若直接遇见换行符;若直接遇见换行符或结束符,或结束符,pc所指数组不变,返回空指针;若读所指

99、数组不变,返回空指针;若读入长度超出数组长度,数组改变,会出现内存写入长度超出数组长度,数组改变,会出现内存写问题(超出数组长度)。例如:问题(超出数组长度)。例如:char cArr11;gets(cArr); /* 或或 char * pc=cArr; gets(pc); 也可以也可以*/输入大于等于一个字符小于等于十个字符时,正常;输入大于等于一个字符小于等于十个字符时,正常;直接输入换行符,直接输入换行符,pc数组不变,返回空指针;数组不变,返回空指针;输入超过十个字符,会出现内存写问题(超出数组长输入超过十个字符,会出现内存写问题(超出数组长度)。度)。2021/6/1687C程序设

100、计快速进阶大学教程2024/8/248811.5. 3 字符串函数字符串函数 2. 字符串输入函数字符串输入函数gets规格说明:规格说明:char * gets(char *pc);例例11.24 #include int main() char cArr15; printf(input string:n); gets(cArr); printf(output string:n); puts(cArr); return 0;input string:C Languageoutput string:C Language 当输入的字符串中含当输入的字符串中含有空格时,输出仍为有空格时,输出仍为全

101、部字符串。说明全部字符串。说明gets函数并不以空格函数并不以空格作为字符串输入结束作为字符串输入结束的标志,而只以换行的标志,而只以换行作为输入结束,这是作为输入结束,这是与与scanf函数的不同。函数的不同。2021/6/1688C程序设计快速进阶大学教程2024/8/248911.5. 3 字符串函数字符串函数 3. 测字符串长度函数测字符串长度函数strlen规格说明:规格说明:int strlen (const char *pc);功能描述:计算功能描述:计算pc所指向的串的长度。所指向的串的长度。函数参数:函数参数:pc可以使指针变量,也可以是字符数组名。可以使指针变量,也可以是字

102、符数组名。函数返回值:返回函数返回值:返回p1指向数组长度,空字符之前的字指向数组长度,空字符之前的字符个数。符个数。例如:例如:char cArr=I, ,l, o, v, e, 0, C, , L, a, n, g, u, a, g, e, 0;strlen(cArr)的值为的值为6,以碰到第一个空字符的长度为,以碰到第一个空字符的长度为准,也就是说准,也就是说cArr当作字符串看时,只包括当作字符串看时,只包括I love。2021/6/1689C程序设计快速进阶大学教程2024/8/249011.5. 3 字符串函数字符串函数 4. 字符串连接函数字符串连接函数strcat规格说明:规

103、格说明:char * strcat (char *pc1 , const char *pc2);功能描述:把字符指针功能描述:把字符指针pc1所指向的字符数组的末尾添加所指向的字符数组的末尾添加pc2所指向的串所指向的串(包括结尾的空字符在内)的副本,(包括结尾的空字符在内)的副本,pc2所指向的串的第一个字符覆所指向的串的第一个字符覆盖盖pc1所指向的串末尾的空字符。所指向的串末尾的空字符。函数参数:函数参数:pc1必须是字符数组名或指向字符数组的指针变量,不可以使用必须是字符数组名或指向字符数组的指针变量,不可以使用指针变量指向字符串常量,因为常量空间不允许改变;指针变量指向字符串常量,因

104、为常量空间不允许改变;pc2可以使指可以使指针变量,也可以是字符数组名。针变量,也可以是字符数组名。函数返回值:返回函数返回值:返回p1;若连接后的;若连接后的pc1长度超出长度超出pc1指向数组长度,会出现指向数组长度,会出现内存写问题(超出数组长度)。内存写问题(超出数组长度)。char cArr20= I love ;char *pc2=C Language;strcat(cArr,pc2);连接后的连接后的cArr值为:值为:I love C Language要注意的是,参数要注意的是,参数1对应的字符数组应定义足够的长度(参数对应的字符数组应定义足够的长度(参数1指向数组长指向数组长

105、度大于等于度大于等于strlen(参数参数1)+strlen(参数参数2)+1),否则不能全部装入被连),否则不能全部装入被连接的字符串。接的字符串。2021/6/1690C程序设计快速进阶大学教程2024/8/249111.5. 3 字符串函数字符串函数 5. 字符串拷贝函数字符串拷贝函数strcpy规格说明:规格说明:char * strcpy (char *pc1 , const char *pc2);功能描述:把字符指针功能描述:把字符指针pc2所指向的串(包括结尾的空字符在内)复制到所指向的串(包括结尾的空字符在内)复制到pc1所指向的字符数组。所指向的字符数组。函数参数:函数参数:

106、pc1必须是字符数组名或指向字符数组的指针变量,不可以使用必须是字符数组名或指向字符数组的指针变量,不可以使用指针变量指向字符串常量,因为常量空间不允许改变;指针变量指向字符串常量,因为常量空间不允许改变;pc2可以使指可以使指针变量,也可以是字符数组名。针变量,也可以是字符数组名。函数返回值:返回函数返回值:返回p1;若复制后的;若复制后的pc1长度超出长度超出pc1指向数组长度,会出现指向数组长度,会出现内存写问题(超出数组长度)。内存写问题(超出数组长度)。char cArr20= I love ;char *pc2=C Language;strcpy(cArr,pc2);复制后的复制后

107、的cArr值为:值为:C Language要注意的是,参数要注意的是,参数1对应的字符数组应定义足够的长度(参数对应的字符数组应定义足够的长度(参数1指向数组长指向数组长度大于等于度大于等于strlen(参数参数2)+1),否则不能全部装入被连接的字符串。),否则不能全部装入被连接的字符串。2021/6/1691C程序设计快速进阶大学教程2024/8/249211.5. 3 字符串函数字符串函数 6. 字符串比较函数字符串比较函数strcmp规格说明:规格说明:int strcmp (const char *pc1 , const char *pc2);功能描述:按照功能描述:按照ASCII码

108、顺序比较字符指针码顺序比较字符指针pc1和和pc2所指向的所指向的串的大小。串的大小。函数参数:函数参数:pc1、pc2可以使指针变量,也可以是字符数组名。可以使指针变量,也可以是字符数组名。函数返回值:函数返回值: pc1所指向的字符串所指向的字符串=pc2所指向的字符串,返回值所指向的字符串,返回值0; pc1所指向的字符串所指向的字符串pc2所指向的字符串,返回值大于所指向的字符串,返回值大于0;pc1所指向的字符串所指向的字符串pc2 /*这是在比较两个地址值。这是在比较两个地址值。*/2021/6/1693C程序设计快速进阶大学教程2024/8/249411.5. 3 字符串函数字符

109、串函数 7. 字符串查找函数字符串查找函数strstr规格说明:规格说明:char * strstr (const char *pc1 , const char *pc2);功能描述:查找字符指针功能描述:查找字符指针pc1所指向字符串中第一次所指向字符串中第一次出现出现pc2所指向字符串(不包括空字符)的地址。所指向字符串(不包括空字符)的地址。函数参数:函数参数:pc1、pc2可以使指针变量,也可以是字符可以使指针变量,也可以是字符数组名。数组名。函数返回值:返回字符指针函数返回值:返回字符指针pc1所指向字符串中第一所指向字符串中第一次出现次出现pc2所指向字符串(不包括空字符)的地址。

110、所指向字符串(不包括空字符)的地址。若不出现返回空指针。若不出现返回空指针。2021/6/1694C程序设计快速进阶大学教程2024/8/249511.5.4 字符串程序举例字符串程序举例 例例11.25 计算正文中某单词出现次数计算正文中某单词出现次数#include#includeint main() char cArrText80; char cArrWord10; int iSum=0; char *pc=cArrText; int iWordLength;/*单词长度单词长度*/ gets(cArrText); gets(cArrWord); iWordLength=strlen(c

111、ArrWord); while(pc!=NULL) pc=strstr(pc,cArrWord);/*查找单词单词起始地址查找单词单词起始地址*/ if(pc!=NULL) iSum+; pc=pc+iWordLength;/*移动到找到单词之后,作为下次查找的起始地址移动到找到单词之后,作为下次查找的起始地址*/ printf(正文:正文:n); puts(cArrText); printf(单词:单词:n); puts(cArrWord); printf(出现次数出现次数%d,iSum); return 0;重点:重点:下一次定位下一次定位2021/6/1695C程序设计快速进阶大学教程2

112、024/8/249611.5.4 字符串程序举例字符串程序举例 例例11.26 姓名按照从小到大字典序排序姓名按照从小到大字典序排序#include#includeint main() /* 每行一个一维字符数组每行一个一维字符数组 */ char cArrName520=Zhang,Li,Wang,Zhao,Qian; char cArrTemp20; int iMin,i1,i2; for(i1=0;i14;i1+) iMin=i1;for(i2=i1+1;i20)/*比较大小比较大小*/ iMin=i2;if(i1!=iMin) /* 交换交换 */ strcpy(cArrTemp,cA

113、rrNamei1); strcpy(cArrNamei1,cArrNameiMin); strcpy(cArrNameiMin,cArrTemp); for(i1=0;i15;i1+)puts(cArrNamei1);/* cArrNamei1等价于一个一维数组等价于一个一维数组 */ return 0;重点:重点:1.每行为一维数组每行为一维数组2.比较不能用关系运算比较不能用关系运算3.交换不能用赋值交换不能用赋值2021/6/1696C程序设计快速进阶大学教程2024/8/249711.5.5 main函数参数函数参数 main()函数以前作为主调函数处理,允许函数以前作为主调函数处理,

114、允许main()调用其它函数并传递调用其它函数并传递参数。事实上,参数。事实上,main()函数既可以是无参函数,也可以是有参的函数既可以是无参函数,也可以是有参的函数。函数。其它任何函数均不能调用其它任何函数均不能调用main()函数。当然也同样无法向函数。当然也同样无法向main()函数函数传递,只能由程序之外传递而来。传递,只能由程序之外传递而来。main()函数的带参的形式:函数的带参的形式: int main(int argc,char * argv ) . 从函数参数的形式上看,包含一个整型和一个指针数组。当一个从函数参数的形式上看,包含一个整型和一个指针数组。当一个C的的源程序经

115、过编译、链接后,会生成扩展名为源程序经过编译、链接后,会生成扩展名为.exe的可执行文件,的可执行文件,main()函数只能由系统在启动运行时传递参数函数只能由系统在启动运行时传递参数完整的运行命令应包括两部分:命令与相应的参数。其格式为:完整的运行命令应包括两部分:命令与相应的参数。其格式为: 命令命令 参数参数1参数参数2.参数参数n 2021/6/1697C程序设计快速进阶大学教程2024/8/249811.5.5 main函数参数函数参数 例例11.27 计算命令行两个整数串参数的和计算命令行两个整数串参数的和#includeint main(int argc,char *argv)

116、int i1,i2; /*要求至少有要求至少有3个参数:命令本身也算一个,另外两个整数串个参数:命令本身也算一个,另外两个整数串*/ if(argc11_27.exe 23 4523+45=682021/6/1698课堂练习课堂练习1.编写函数,通过指针连接两个字符串。不允许用编写函数,通过指针连接两个字符串。不允许用标准函数。标准函数。2.删除字符串删除字符串str1中的所有子串中的所有子串str2。如。如str1=abcdabac,str2=ab,计算结果:,计算结果:str1=cdac。C程序设计快速进阶大学教程2024/8/24992021/6/1699C程序设计快速进阶大学教程202

117、4/8/2410011.6 动态空间管理动态空间管理 在变量存储类别部分,介绍过在变量存储类别部分,介绍过C语言内存分为语言内存分为3个区,有了字符个区,有了字符串和动态空间后可以把它增加到串和动态空间后可以把它增加到5五个区:五个区:动态存储区(栈)动态存储区(栈):用来存放函数的形参和函数内的局部变量。:用来存放函数的形参和函数内的局部变量。函数调用时分配空间,在函数执行完后由编译器自动释放。函数调用时分配空间,在函数执行完后由编译器自动释放。 堆区堆区:用来存放由动态分配函数(如:用来存放由动态分配函数(如malloc)分配的空间。是)分配的空间。是由动态分配函数分配的,并且必须使用由动

118、态分配函数分配的,并且必须使用free释放。如果忘释放。如果忘记用记用free释放,会导致所分配的空间一直占着不放,导致释放,会导致所分配的空间一直占着不放,导致内存泄露。内存泄露。 静态存储区静态存储区:用来存放全局变量和静态变量。存在于程序的整:用来存放全局变量和静态变量。存在于程序的整个运行期间。个运行期间。 字符串常量区字符串常量区:例如:例如char *c = “123456”;则;则”123456”为字为字符串常量,存放于字符串常量区。存在于程序的整个运行符串常量,存放于字符串常量区。存在于程序的整个运行期间。不同函数使用同的字符串常量在内存中会共用。期间。不同函数使用同的字符串常

119、量在内存中会共用。 程序代码区程序代码区:用来存放程序的二进制代码。:用来存放程序的二进制代码。2021/6/16100C程序设计快速进阶大学教程2024/8/2410111.6 动态空间管理动态空间管理 1. malloc函数:开辟指定大小的存储空间,并返回该存储区的起始地址。函数:开辟指定大小的存储空间,并返回该存储区的起始地址。void *malloc(unsigned int size);其中其中size为需要开辟的字节数。函数返回一个指针,该指针不指向具体的类为需要开辟的字节数。函数返回一个指针,该指针不指向具体的类型(型(void),当将该指针赋给具体的指针变量时,需进行强制类型转

120、),当将该指针赋给具体的指针变量时,需进行强制类型转换(约定成某种类型)。若换(约定成某种类型)。若size超出可用空间,则返回空指针值超出可用空间,则返回空指针值NULL。例如:例如:float *pf1;int *pi1;pf1=(float *)malloc(8);*pf1=1.2; /* pf10=1.2*/*(pf1+1)=2.4; /* pf11=2.4*/pi1=(int *)malloc(10*sizeof(int);for(int i1=0;i110;i1+) scanf(%d,pi1+); 分别开辟了分别开辟了8字节和字节和104(约定(约定int4字节)字节的存储空间,并

121、向其中存入字节)字节的存储空间,并向其中存入数据。数据。2021/6/16101C程序设计快速进阶大学教程2024/8/2410211.6 动态空间管理动态空间管理 2. calloc函数:按所给数据个数和每个数据所占字节函数:按所给数据个数和每个数据所占字节数开辟存储空间。数开辟存储空间。void *calloc(unsigned int num, unsigned int size);其中其中num为数据个数,为数据个数,size为每个数据所占字节数,为每个数据所占字节数,故开辟的总字节数为故开辟的总字节数为num*size。函数返回该存储。函数返回该存储区的起始地址。若区的起始地址。若n

122、um*size超出可用空间,则返超出可用空间,则返回空指针值回空指针值NULL。例如:例如:上例中上例中pi12可改写为可改写为pi1=(int *)calloc(10, sizeof(int);2021/6/16102C程序设计快速进阶大学教程2024/8/2410311.6 动态空间管理动态空间管理 3. realloc函数:重新定义所开辟内存空间的大小。函数:重新定义所开辟内存空间的大小。void *realloc(void *ptr, unsigned int size)其中其中ptr所指的内存空间是用前述函数已开辟的,所指的内存空间是用前述函数已开辟的,size为新的空间大小,其值可

123、比原来大或小。函数返为新的空间大小,其值可比原来大或小。函数返回新存储区的起始地址(该地址可能与以前的地回新存储区的起始地址(该地址可能与以前的地址不同)。若址不同)。若size超出可用空间,则返回空指针超出可用空间,则返回空指针值值NULL。例如:例如:pf1=(float *)realloc(pf1,16);将原先开辟的将原先开辟的8个字节调整为个字节调整为16个字节。可以理解为个字节。可以理解为新申请新申请16个字节,把原来空间的个字节,把原来空间的8个字节复制到前个字节复制到前8个字节,然后返回新空间地址,并释放原来的个字节,然后返回新空间地址,并释放原来的8字节空间。字节空间。202

124、1/6/16103C程序设计快速进阶大学教程2024/8/2410411.6 动态空间管理动态空间管理 4. free函数:将以前开辟的某内存空间释放。函数:将以前开辟的某内存空间释放。void free(void *ptr)其中其中ptr为存放待释放空间起始地址的指针变量,函数为存放待释放空间起始地址的指针变量,函数无返回值。应注意:无返回值。应注意:ptr所指向的空间必须是前述所指向的空间必须是前述函数所开辟的。若以前开辟的空间不释放,将会函数所开辟的。若以前开辟的空间不释放,将会一直占用空间,有可能造成内存泄露,直到整个一直占用空间,有可能造成内存泄露,直到整个程序结束。程序结束。例如:

125、例如:free(void *)pf1);将上例开辟的将上例开辟的16个字节释放。可简写为个字节释放。可简写为free(pf1);由系统自动进行类型转换。由系统自动进行类型转换。2021/6/16104C程序设计快速进阶大学教程2024/8/2410511.6 动态空间管理动态空间管理 几种空间申请方法,当空间不够时,都会申请不成功,几种空间申请方法,当空间不够时,都会申请不成功,返回返回NULL。通常情况下,动态空间申请时都应该。通常情况下,动态空间申请时都应该检测一下空间是否申请成功,然后再使用。检测一下空间是否申请成功,然后再使用。例如:例如:int *pi1;void *pv;pv=ma

126、lloc(10*sizeof(int);if(pv=NULL) exit(0); /*退出程序退出程序*/pi1=(float *)pv;2021/6/16105C程序设计快速进阶大学教程2024/8/2410611.6 动态空间管理动态空间管理 例例11.28 存储空间类型存储空间类型#include#includeint i1=0; /* 静态存储区静态存储区 */int main() int i2; /* 动态存储区(栈)动态存储区(栈) */ char cArr3 = abc; /* cArr在动态存储区(栈),在动态存储区(栈),abc在字符串常量区在字符串常量区*/ char *p

127、c1,*pc2; /* 动态存储区(栈)动态存储区(栈) */ char *pc3 = 123456; /* p3在动态存储区(栈)在动态存储区(栈),123456在字符串常量区在字符串常量区*/ static int i3 =0; /* 静态存储区静态存储区 */ pc1 = (char *)malloc(10); /* pc1在动态存储区(栈),分配的在动态存储区(栈),分配的10字节在堆区字节在堆区*/ pc2 = (char *)malloc(20); /* pc2在动态存储区(栈),分配的在动态存储区(栈),分配的20字节在堆区字节在堆区*/ strcpy(pc1,123456); /* pc1在动态存储区(栈),在动态存储区(栈),123456在字符串常量区在字符串常量区*/ free(pc1); /*释放释放pc1所指向空间所指向空间*/free(pc2); /*释放释放pc2所指向空间所指向空间*/ return 0; 2021/6/16106 结束语结束语若有不当之处,请指正,谢谢!若有不当之处,请指正,谢谢!

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 建筑/环境 > 施工组织

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号