




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、C语言程序设计教程(第4版),第8章 指针,李丽娟 2013年2月,第8章 指针,本章主要内容 1. 指针的概念 2. 指针与变量的关系 3. 指针的使用方法和运算 4. 指针的作用 5. 指针与函数的关系 6. 指针与数组的关系,8.1 指针的概念,重要概念: 指针也是变量。 指针变量只能存放变量的地址。 指针变量也分别有不同的类型,用来保存不同类型变量的地址。 变量存储的概念: 假设有:int i =5; char ch = A; float x =7.34; 各变量占用内存单元的概念情况如图所示:,8.1 指针的概念,8.1.1 指针变量的定义 指针变量的定义形式: 存储类型 数据类型
2、*指针变量名=初始值; 如:int a,*p= t 为指向单精度浮点型变量的指针。,8.1 指针的概念,基本概念: 指针变量的值是某个变量的地址。 地址是内存单元的编号,每一个在生命周期内的变量在内存中都有一个地址,该地址不会因为其变量值的变化而变化。 内存单元编号通常用无符号的长整型表示,亦即指针变量的值是无符号的长整型。 特别提示:要区分指针变量所指的值和变量的值。,8.1 指针的概念,8.1.2 指针变量的使用 必须先将指针与变量的地址相关联,然后才能使用指针。 关联方式: 初始化; 赋值 赋值格式: 则表示p不指向任何存储单元。,8.1 指针的概念,指针的引用: 指针引用格式: *指针
3、变量名 代表所指变量的值; 指针变量名 代表所指变量的地址。 例如: int i, *p; float x, *t; p= /*相当于x=12.34 */,8.1 指针的概念,对于:int i, *p; float x, *t; p= 变量及指针的存储关系示意图如图所示:,8.1 指针的概念,对于:int i, *p; float x, *t; p= 变量i的地址:p、 a=*p+*s; printf(a=%dn*p=%lun*s=%lu,a,p,s); 将程序放到不同的环境下运行,观察结果,思考。,8.2 指针的运算,对指针的运算,实际是对地址进行操作。 8.2.1 指针的算术运算 指针的运
4、算通常只限于: 算述运算符:+、+ +、 。 关系运算符:、=、!=、=、 +、+ +代表指针向前移(地址编号增大)。 、 代表指针向后移(地址编号减小)。 设p、q为某种类型的指针变量,n为整型变量。 则:p+n、p+、+p、p 、 p、pq的运算结果仍为指针。,8.2 指针的运算,若有:int a=3, *p= 假设a的地址为3000,则p=3000。 变量a与指针p的存储关系如图(a)所示。 执行语句:pp+1;后,指针p向前移动一个位置。 如果a是用2个字节,则p的值为3002,如图(b)所示; 如果a占用4个字节,则p的值为3004,如图(c)所示。,注意:指针p指向下一个单元,但*
5、p的值未知。,例3: 阅读程序example8_3 ,了解指针的值的变化。 #include main() int i=108,*pi= /* 未知单元的值 */ ,8.2 指针的运算,8.2 指针的运算,8.2.2 指针的关系运算 指针的关系运算常用于比较两指针是否指向统一变量。 假设有:int a, *p1, *p2; p1= ,8.3 指针与数组的关系,重要概念: C语言规定:数组名就是数组的首地址。 数组元素在内存中是连续存放的。 引申: 指针可以指向数组元素的地址,也可以指向数组名。 8.3.1 指向一维数组的指针 若有:int a5, *p; p=a;,8.3 指针与数组的关系,指
6、针p与数组a的存储关系如图示。 a、 p=a; 则: 表示数组a的地址:p、a、 char ch2=a,b,*pc; pa=a; pc= ,8.3 指针与数组的关系,注意:指向数组的指针和指向简单变量的指针的区别, 例6:阅读程序example8_6.c,了解指向数组的指针和指向变量的指针的关系。 #include main() int a1=123,a2=234,a3=345,i; int *p1,*p2,*p3; int as3=1,2,3,*ps; p1= ,8.3 指针与数组的关系,8.3.2 指向多维数组的指针 对多维数组而言,数组名同样代表着数组的首地址。 若有:int a34;
7、则:数组首地址的表示:a、a0、 这个语句在概念上容易混淆,有些编译时会有警告提示:“Suspicious Pointer Conversion”,应该避免这种情况。,8.3 指针与数组的关系,对于int a34, *p=a0; 指针p的使用方法同一维数组的指针。 p+的结果为指向下一个元素的地址。 指针p与数组的地址关系: p=a+1 移到下一行的地址 p=a0+1 p= int *p; p=a0; printf(1:-n); printf(a=%lun,a); printf(*a=%lun,a); printf(p=%lun,p); printf(a0=%lun,a0); printf(,
8、8.3 指针与数组的关系,printf(2:-n); printf(a+1=%lun,a+1); printf(*a+1=%lun,*a+1); printf(p+1=%lun,p+1); printf(a0+1=%lun,a0+1); printf( ,8.3 指针与数组的关系,分析程序中指针变量、数组名之间的地址关系,掌握指针与二维数组的联系。 例8:阅读程序example8_8.c ,了解指针与数组元素的关系。 分析程序中用指针引用数组元素的表达式。 结论: 引用同一个数组元素,有多种不同的方法。 使用时选择一种自己认为最合适的。,8.3 指针与数组的关系,C语言还提供了一个指向多个元素
9、的指针,它具有与数组名相同的特征,可以更方便地用指针来处理数组,指向多个元素指针的定义形式为: 数据类型(*指针变量名)N; 其中,N是一整型常量。 例如: int (*p)4; /* 指向具有4个整型元素的数组 */ float (*pt)3; /*指向具有3个浮点型元素的数组 */ 若有: pp+1;,则p的值增加16。 pt=pt+1;,则p的值增加12。,8.3 指针与数组的关系,例9:阅读程序example8_9.c,了解指向简单变量的指针p和指向多个元素的指针t的特性。掌握它们的使用方法。 注意程序中指针p与指针t的不同特性。 例10:阅读程序example8_10.c,了解用指针
10、引用数组元素的方法。,8.3 指针与数组的关系,8.3.3 字符指针 指向字符型变量的指针具有另外的特性。 如:char *sp; sp可以指向字符、字符数组,也可以指向一个字符串。 如有: char *sp= How are you? “; char *cp; cp=sp; 则: 指针sp和cp之间的关系如图示。,8.3 指针与数组的关系,若有: char *sp= How are you? ; 引用字符串中某个字符,可以通过以下两种方式。 * (sp+i) spi 注意: 上面的第种情况:sp并不是数组。 如果用字符指针指向了某个字符串时,可以像引用数组元素那样,用spi来引用字符串中的字
11、符;但不可以改变字符串中spi所代表的这个字符。 如果改变指针变量的值,实际上是改变了指针的指向。,8.3 指针与数组的关系,例11:阅读程序example8_11.c,了解字符指针输出数组中的字符方法。 请分析程序中指针p引用字符数组元素的方法。 利用字符指针,可以很方便地完成许多字符串问题的处理。 请改写程序,采用直接输出数组元素的方法,输出字符数组中的内容,并与上面的程序进行比较。,8.3 指针与数组的关系,8.3.4 指针数组 指针数组:数组中的每一个元素都是指针。 指针数组的定义形式: 存储类型 数据类型 *数组名元素个数 例如:int *p5; 则:p为指针数组,共有5个元素:p0
12、、p1、p2、p3、p4 每一个元素都是指向整型变量的指针。 通常可用指针数组来处理字符串和二维数组。 例12:阅读程序example8_12.c,了解用指针数组访问二维数组中的每一个元素的方法。,8.3 指针与数组的关系,例13: 编写程序,对一组英文单词字符串进行按字典排列方式(从小到大)进行排序。 分析:可以用字符指针数组来保存每一个字符串,这样数组中的每一个元素就可以指向一个字符串,通过对数组元素中的字符进行比较,就可以完成字典排序。 设计一个排序函数:void sort(char *words , int n),可以对words中的n个字符串进行排序。 程序:example8_13.
13、c 分析程序中排序函数void sort(char *words , int n)的实现算法。 思考:其他的算法。,8.4 指针作为函数的参数,指针作为变量,也可以用来作为函数的参数。 若函数的参数类型为指针型,则实参与形参的传递是一种“传址”方式。 如果函数中有对形参值的改变,实际上也就是修改了实参的值。 例14:从键盘输入任意两个整数作为两个变量的值,编写程序,将这两个变量的值进行交换。 分析:可设计函数void swap(int *p1,int *p2),通过指针与变量的关系,交换指针p1和p2所指变量的值。 程序:example8_14.c,8.4 指针作为函数的参数,例15:用字符指
14、针指向从键盘输入的字符串,编写程序,计算输入的字符串的长度。输入结束时的换行符不作为字符计入其长度。 分析: 用字符指针来表示字符串时,指针指向的是字符串的首地址。 输入结束时,系统会将结束标志0置于字符串的尾部。 计算字符串的长度时,结束标志是不计数的。 若输入的字符串为“abcdefg”,则占用的内存单元为8个,但字符串的长度为7。 设计函数int getlength(char *str),计算str所指字符串的长度。 字符串的结束标志和输入的换行符均不计入字符的长度。 程序:example8_15.c,8.4 指针作为函数的参数,请分析统计字符串长度函数的算法。 思考: 程序中结束标志(
15、0)和换行符(n)均不计入字符的长度,若用如下的程序语句: while(*p!=0 | *p!=n) p+; 来统计字符串的长度,是否能达到要求?为什么?,8.5 函数的返回值为指针,指针作为一种变量,也可以作为函数的返回值。 若函数的返回值为指针,则称其为指针函数。 指针函数的定义形式为: 存储类型 数据类型 *函数名 (形参表); 例如: int *fun1( ); /* 函数返回一个指向整型变量的指针 */ char *fun2( ); /* 函数返回一个指向字符型变量的指针 */ 例16:编写程序,从键盘输入一个字符ch,在字符串string中查找是否存在有该字符,若存在,给出该字符在
16、字符串中第1次出现的位置。 分析:对于指定的字符串string,在内存中会分配一段连续的空间存储string中每一个字符的值,将输入的字符ch与字符串string中的每一个字符进行比较,如果相等,则返回字符串中与字符ch相等的字符的位置(地址)。 设计函数char* search(char *str,char c), 功能:在str所指的字符串中,查找是否有字符变量c的字符, 如果有,返回字符串中相同字符的地址。 程序:example8_16.c,* 8.6 指向函数的指针,函数指针就是指向函数的指针,用函数指针存放函数的入口地址。 函数指针的定义形式: 存储类型 数据类型 (*变量名)();
17、 数据类型为指针所指函数的返回值的数据类型。 请注意定义中的两个圆括号。 如:int (*p)( ); p是一个函数指针变量,所指函数的返回值为int型。 为函数指针赋值: 函数指针变量函数名; 用函数指针调用函数,调用形式为: (*函数指针变量名)(实参表); 例17:阅读下面的程序,了解函数指针的使用。 程序:exmaple8_17.c,*8.6 指向函数的指针,提示: 仅仅用函数指针替代函数名去调用函数(如程序exam8-17.c),就失去了函数指针本身的意义。 使用函数指针的意义: 将函数指针设计成函数的形参,调用函数时,参数传递的是函数名。 例如: int sub(int (*p1)
18、( ), int (*p2)( ), int a , int b) int m, n; m=(*p1)(a, b) ; n=(*p1)(m, a+b); return m+n; 若有两函数:fun1、fun2, 则:调用函数:sub(fun1, fun2, x,y),达到调用其他函数的目的。 这种方法主要表现提高程序设计的模块化程度。 例18:阅读程序exmaple8_18.c ,了解函数指针作为函数参数的作用。,*8.7 main函数的参数,C语言规定:main函数也可以带参数,参数的个数最多为3个。 (注:参数名及参数的顺序和类型是固定不变的)。 main函数的参数形式如下: main(i
19、nt argc, char *argv , char *env ) 几点说明: main函数的形参是具有特定的意义的。 疑问: 每一个C语言程序都是从main函数开始执行的,参数是怎样传递给main函数的? 带有main函数参数的程序,执行方式应有所不同。 执行方式:以输入命令方式执行程序。 (不适合在集成开发环境下运行) 参数来自于命令方式下执行程序时输入的一些信息。,*8.7 main函数的参数,对于 main(int argc, char *argv , char *env ) 各参数的含义如下: 第1个参数(int argc):执行该程序时输入的参数个数。 每个参数都用字符串来表示,字
20、符串之间由空格分开。 第2个参数(char *argv ):指针数组,每一个元素分别指向执行该程序时输入的每一个参数。 元素个数输入的的参数个数(argc)相等。 第3个参数(char *env ):指针数组,每一个元素分别指向系统的环境变量字符串。 元素个数与系统的环境变量个数相等。 设程序exam.c中main函数中带有参数; 生成的执行程序为:exam.exe;,*8.7 main函数的参数,执行该程序时,输入的命令方式为: exam 参数1至参数(n1)必须是合法的字符串。 则main函数中的参数值为: argc=n; argv0= exam“ argv1= 参数1“ argvn-1=
21、 参数(n-1)。 env0envm:系统环境变量。 一般而言,不同的机器会有不同的结果。,*8.7 main函数的参数,根据C语言的规则,main函数参数的个数允许有不同,但参数的顺序不允许变化。 因此,main函数参数的形式就只有如下4种: 1main( ) 2main(int argc) 3main(int argc, char *argv ) 4main (int argc, char *argv , char *env ) 例19:阅读程序example8_19.c ,了解main函数参数的特点,分别在命令方式下(如DOS模式)和集成开发环境下运行该程序,看看有什么变化与不同。,*8
22、.8 指向指针的指针,指针作为一种变量,也是要占用内存空间的。 C语言提供另一种变量来保存指针变量的地址。 指向指针变量的指针,它的值为指针变量的地址。 定义形式为: 存储类型 数据类型 *指针变量名; 例如: int a=6, *p, *pp; p= 则:*pp的值为p的地址值。 *pp的值等于*p(变量a的值)。 a、p、pp的关系如图所示。,8.8 指向指针的指针,例20:程序example8_20.c是利用指向指针的指针变量,访问二维字符数组,请阅读程序,了解指向指针的指针变量的作用和使用方法。 提示: 要注意区分指向指针的指针与二维数组名的关系。 程序中语句:ppw=pw;的作用是将
23、指针数组的首地址传递给指向指针的指针变量。 因此,表示第i行的首地址应该用*(ppw+i)而不是ppw+i。,8.10 程 序 范 例,例22:下面的程序是一种变化的约瑟夫问题,有30个人围坐一圈,从1到M按顺序编号,从第1个人开始循环报数,凡报到7的人就退出圈子,请按照顺序输出退出人的编号。 分析:设置两个整型数组:person和pout。person用来表示30个人围成的一个队列圈。 pout用来表示出队的结果。 规定person元素的值只有两种情况:0和非0。非0表示该元素还在队列内;0表示该元素已出队列。 从person的第1个元素开始报数,报到第7的时候,将该元素的值改为0,同时将该
24、元素的下标值按顺序赋给另一个整型数组pout,当数组person中的所有元素的值为0时,输出顺序就生成了。 设计函数:void goout(int pp,int po,int n),从数组pp的第1个元素开始,按n循环报数出队,出队顺序保存到数组po中。 程序如下:example8_22.c,8.10 程 序 范 例,算法的关键有两个地方值得注意: 1当队列报数到达最后1个元素的时候,要让指针回到数组的起始位置; 2对已经出队的元素值要赋0值。 思考: 分析程序的算法思想; 设计其他算法,并编写程序验证。,8.10 程 序 范 例,例24:编写程序,采用冒泡法对一组从键盘输入的任意个整数(个数
25、50)进行升序排序,输出排序后的结果。 分析:冒泡排序就是将最小的数放在最前面。可以将输入的数据保存到数组,再对数组元素进行排序。 算法思想: 程序:example8_24.c,8.10 程 序 范 例,例25:编写两个函数,分别完成洗牌和发牌。 1void shuffle(int wDeck413);完成洗牌的功能。 2void deal(int a413,char *pf,char *pw);完成发牌的功能。 编写程序,测试函数的功能。 分析: 不计大王和小王,一副牌有52张(4种花色,每个花色有13张牌) 用一个413的整型二维数组deck表示纸牌的面值和花色。 数组的行与花色对应: 第1行代表红桃(Hearts); 第2行代表方块(Diamonds); 第3行代表梅花(Clubs); 第4行代表黑桃(Spades)。 数组的列数与面值对应:第1列到第13列对应于A,1,210,J,Q,K。 分别用字符指针
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 【正版授权】 ISO/IEC 18012-4:2025 EN Information technology - Home electronic system (HES) - Guidelines for product interoperability - Part 4: Event encoding
- 惠州市中考数学试卷
- 海泉小升初数学试卷
- 河南平舆小升初数学试卷
- 医院被服管理课件
- 健康管理师配套课件
- 健康管理师总结课件
- 2025年中国液位显示仪行业市场前景预测及投资价值评估分析报告
- 中国劈开式皮带轮行业市场调研分析及投资前景预测报告
- 健康社会课件图片素材
- 生活垃圾分拣技术的研究现状及发展趋势分析
- 农业合作社农机具租赁合同模板
- 2025-2030年中国电镀工业前景规划及投资决策建议研究报告
- 小学生消防暑期安全
- 《海运出口操作》课件
- 《四川省信息化项目费用测算标准》
- 辽宁省沈阳市皇姑区岐山小学-2024-2025年第一学期班主任工作总结(勤于细微)【课件】
- DB33 1121-2016 民用建筑电动汽车充电设施配置与设计规范
- 电信研发工程师L1认证培训考试复习题库(含答案)
- DB12T 1102-2021 邮政投递服务规范
- 反酸病因介绍
评论
0/150
提交评论