C语言程序设计ppt第9章课件.ppt

上传人:小飞机 文档编号:2075947 上传时间:2023-01-07 格式:PPT 页数:105 大小:649KB
返回 下载 相关 举报
C语言程序设计ppt第9章课件.ppt_第1页
第1页 / 共105页
C语言程序设计ppt第9章课件.ppt_第2页
第2页 / 共105页
C语言程序设计ppt第9章课件.ppt_第3页
第3页 / 共105页
C语言程序设计ppt第9章课件.ppt_第4页
第4页 / 共105页
C语言程序设计ppt第9章课件.ppt_第5页
第5页 / 共105页
点击查看更多>>
资源描述

《C语言程序设计ppt第9章课件.ppt》由会员分享,可在线阅读,更多相关《C语言程序设计ppt第9章课件.ppt(105页珍藏版)》请在三一办公上搜索。

1、2023/1/7,华中科技大学计算机学院,1,C语言程序设计,The C Programming Language,华中科技大学计算机学院曹计昌,2023/1/7,华中科技大学计算机学院,2,9.1 指针的概念与指针的使用,9.1.1 指针的概念 数据(变量、常量)(根据类型)占有一定数目的连续存储单元;数据的连续存储单元首地址称为数据的地址。变量的地址称为指针,存放地址数据的变量称为指针变量。指针也是一种变量,也要占用一定的内存单元。指针的特殊之处在于它存放的是另一个变量所占存储单元的起始地址。,2023/1/7,华中科技大学计算机学院,3,指针变量的类型由其基类型决定.基类型是指针变量所指

2、(即所指向)变量的数据类型。因此,称指向某种类型变量的指针为该类型的指针。如:指向整型变量的指针称为整型指针,指向字符型变量的指针称为字符指针等。不管是何种类型的指针,所占的存储与机器字长相当.如:16位机,指针占2字节,思考:为什么指针指针有类型?,指针变量的类型,2023/1/7,华中科技大学计算机学院,4,ptr指向x,如果整型变量x的地址是0 xFEC0,x的值是0 xABCD,整型指针ptr的地址是0 xFEBC,整型指针ptr指向整型变量x的内存存储和指向情况可以由下图描述:,2023/1/7,华中科技大学计算机学院,5,9.1.2 指针的声明,声明指针的一般形式:T*标识符1,*

3、标识符2,,*标识符n;其中,T是数据类型。*是指针说明符,用于将其说明的标识符说明为指针类型。标识符1,标识符2,标识符n是T类型的指针的名字.例9.1:char*pc1,*pc2;int*pi;float*pf;,2023/1/7,华中科技大学计算机学院,6,指针变量也可以在声明的时候对其进行初始化,但必须用所指变量的地址进行初始化。初始化后的指针将指向以初值为地址的变量。例9.2 声明指针并初始化。int x=10,*p=,2023/1/7,华中科技大学计算机学院,7,例9.3 给出以下一些复杂声明,解释其含义。,int(*p1)3;double*p25;char(*fp)(int,in

4、t);int*pf(float a);int(*fp_ary2)(char*,int*);,2023/1/7,华中科技大学计算机学院,8,9.1.3 指针的使用,在声明指针变量的前提下,指针的使用首先要获取变量的地址作为指针值,然后要将该指针值赋给指针变量,建立指针变量与被指变量间的指向关系。接下来就是如何通过指针变量来间接访问和操作指针所指的变量。,2023/1/7,华中科技大学计算机学院,9,1.取地址运算符-单目&单目&在C中表示取地址运算。该表达式的一般使用形式是:&右操作数 根据表达式的操作语义可知,右操作数必须是一个左值表达式。如果右操作数的类型是T,则表达式&右操作数的类型是T*

5、。,2023/1/7,华中科技大学计算机学院,10,2.指针的赋值 指针的声明只是创建了指针变量,获得了指针变量的存储,但并没有给出指针变量指向那个具体的变量,此时指针的值是不确定的随机值,指针处于“无所指”的状态。例如:用 int*p;语句来说明p是一个整型指针变量时,p的值是不确定的随机值。此时称p为悬挂指针。,2023/1/7,华中科技大学计算机学院,11,例9.5 设有下面说明:int i,*pi;char c,*pc;float x5,*pf;则:pi=合法有效。,2023/1/7,华中科技大学计算机学院,12,3.间访运算符单目*声明指针的目的是希望通过指针实现对内存中变量的快速访

6、问,必须使用单目*这个间访运算符才能实现利用指针对内存变量的访问。间访的含义是间接访问。单目*运算实际上是单目&运算的逆运算.使用单目*间访变量的一般形式是:*操作数“*操作数”称为间访表达式,它的操作语义是引用以操作数之值为地址的变量。操作数也可以是表达式,但其值必须是地址值。间访表达式的值是一个左值,代表指针所指的变量。而指针所指的变量的类型就是间访表达式运算结果的类型。,2023/1/7,华中科技大学计算机学院,13,例9.6 间访运算符的基本操作举例。设有声明和赋值:char ch=a,*pc=&ch;*pc=b;并且假设字符变量ch的地址是0 x1b2a,试问ch,pc,以及*pc的

7、值是什么?,2023/1/7,华中科技大学计算机学院,14,4.无值型指针 类型为void*的指针称为无值型指针或void指针。C语言规定,任何类型的指针都可以将其值赋给void指针,但是不能对void指针执行间访操作,即对void指针施行“*”操作属于非法操作。int x=1,*px=/*非法*/,2023/1/7,华中科技大学计算机学院,15,9.2 指针运算,指针允许进行算术运算、赋值运算和关系运算。通过指针运算可以快速定位到指定的内存单元,提高程序的执行效率。9.2.1 指针的算术运算1.指针的移动指针的移动指指针在原有位置的基础上,通过加一个整数实现指针的前移(地址增大的方向)或者通

8、过减一个整数实现指针的后移。当然,如果加减的是一个负数,则移动的方向刚好和前面相反。,2023/1/7,华中科技大学计算机学院,16,例9.9 指针的算术运算应用举例(演示EX9_9)。#include stdio.hvoid main(void)int iary5=0,1,2,3,4;int*px=,2023/1/7,华中科技大学计算机学院,17,px+=3;printf(after px plus 3:n);printf(px=%p*px=%dn,px,*px);px-=2;printf(after px minus 2:n);printf(px=%p*px=%dn,px,*px);pri

9、ntf(*(+px)=%dn,*(+px);printf(px=%p*px=%dn,px,*px);printf(*(px+)=%dn,*(px+);printf(px=%p*px=%dn,px,*px);printf(*(-px)=%dn,*(-px);printf(px=%p*px=%dn,px,*px);printf(*(px-)=%dn,*(px-);printf(px=%p*px=%dn,px,*px);,2023/1/7,华中科技大学计算机学院,18,9.2.2 指针的赋值运算和关系运算1.指针的赋值运算 指针的初始化和基本赋值操作前面已有叙述。下面主要进行一些归纳并给出应用的例子

10、,其中利用指针的赋值运算以及类型强制来突破语言的一些制约因素的编程算法和思想可以在底层软件开发时借鉴,达到汇编级别开发的自由度。,2023/1/7,华中科技大学计算机学院,19,指针的赋值运算规则:(1)同类型的指针才可以直接使用赋值操作符进行赋值操作。如:int a3=1,2,3,*p=a,*q=p;(2)如果要实现不同基本类型指针之间的赋值运算,必须使用类型强制。利用指针的赋值运算以及类型强制可以实现一些特殊操作。,2023/1/7,华中科技大学计算机学院,20,例9.11 一个长整型数占4个字节,其中每个字节又分成高4位和低4位。试从长整型数的低字节开始,依次取出每个字节的高4位和低4位

11、并以ASCII码的形式进行显示。,2023/1/7,华中科技大学计算机学院,21,例9.11(演示EX9_11),#include stdio.h“void main(void)long x=0 x1234ABCD,k;char*p=(char*),2023/1/7,华中科技大学计算机学院,22,2 指针的关系运算指针的关系运算指对指针施行诸如:,=,以及!=这样一些比较操作。指针属于一种派生类型,它属于何种类型的指针要受所指变量的类型,即指针的基类型的限制。不同类型的变量在内存中分配的存储不同;对于不同的数据类型,定义于其上的操作和运算也不尽相同。因此,尽管所有指针的值都是二进制正整数,从关

12、系运算的操作语义上看,允许不同类型的指针进行比较没有实际意义,并且只会给语言和程序带来副作用。因此,C语言规定指针的关系运算只能限于同类型指针,不同类型指针之间的关系运算被视为非法操作。,2023/1/7,华中科技大学计算机学院,23,9.3 指针作为函数的参数,9.3.1 形参指针对实参变量的影响 例9.12 被调用函数中对形参的修改无法影响调用函数中实参变量的值举例(演示EX9_12)。#include stdio.hvoid swap(int u,int v)int t;printf(in function swap,before swap,u=%d and v=%dn,u,v);t=u

13、;u=v;v=t;printf(in function swap,after swap,u=%d and v=%dn,u,v);,2023/1/7,华中科技大学计算机学院,24,(演示EX9_12)void main(void)int x,y;printf(input two integers for x and y please!n);scanf(%d%d,2023/1/7,华中科技大学计算机学院,25,程序运行中的输入以及运行结果为:input two integers for x and y please!10 20(键盘输入)in function main,before swap,x

14、=10 and y=20in function swap,before swap,u=10 and v=20in function swap,after swap,u=20 and v=10in function main,after swap,x=10 and y=20,2023/1/7,华中科技大学计算机学院,26,(演示EX9_13)例9.13 以指针作为函数的参数实现变量值的交换。#include stdio.hvoid swap(int*p1,int*p2)int t;t=*p1;*p1=*p2;*p2=t;,2023/1/7,华中科技大学计算机学院,27,void main(voi

15、d)int x,y;printf(input two integers for x and y please!n);scanf(%d%d,2023/1/7,华中科技大学计算机学院,28,程序运行中的输入以及运行结果为:input two integers for x and y please!12 45before swap,x=12 and y=45after swap,x=45 and y=12,2023/1/7,华中科技大学计算机学院,29,对于数组,由于数组名标识的数组的起始地址,故可直接作为指针类型的实参;除此之外,都必须以&变量名的形式给出变量的地址作为实参,以保证在被调用函数中能

16、够操作调用函数中的对应变量。例9.14 将键盘输入的所有数字串逐个的转换为整数,并且依次存放于一个数组中。数字串前面可以加+、-号,各数字串之间至少用一个空格分开,用回车结束输入。演示并解释p267 例9-14,9.3.2 指针作为函数形参的应用,2023/1/7,华中科技大学计算机学院,30,#include ctype.h#define NUMBER 100int getint(int*pn);int getint(int*pn)int c,sign;while(isspace(c=getchar();/*跳过前导空格*/if(!isdigit(c),void main(void)int

17、aNUMBER,i,j,k;printf(input integers ends with Entern);for(i=0;i NUMBER,2023/1/7,华中科技大学计算机学院,31,9.4 数组的指针表示,数组元素既可以用下标表示,也可以用指针表示。对于T类型的数组元素ai,用下标表示时其地址为&ai,用指针表示时其地址为a+i,编译程序计算ai的地址都统一按照:a+i*sizeof(T)的形式进行。其中i*sizeof(T)表示数组元素ai相对该数组的起始地址向后偏移的字节数。由于下标操作符是系统的预定义函数,下标操作实际涉及对系统预定义函数的调用。因此,一般说来,指针运算比数组下标

18、运算的速度要快。,2023/1/7,华中科技大学计算机学院,32,9.4.1 一维数组的指针表示设有说明:int x5;各元素的访问方式:x0、x1、x2、x3、x4*(x+0)、*(x+1)、*(x+2)、*(x+3)、*(x+4)各元素的指针:&x0、&x1、&x2、&x3、&x4x+0、x+1、x+2、x+3、x+4,2023/1/7,华中科技大学计算机学院,33,ISO/IEC 9899中关于数组与指针关系的描述见p70,E1E2与(*(E1)+(E2)因此:ai=(*(a)+(i)=*(a+i)对于:bij,令bi=E1,E2=jbij=*(bi+j)=*(*(a+i)+j)所以:C

19、ijk=*(cij+k)=*(*(ci+j)+k)=*(*(*(c+i)+j)+k)思考:eijklm的间访表示?,2023/1/7,华中科技大学计算机学院,34,迭代处处都存在,上例求bij,Cijk 的间访表示就用到了迭代的方法.求诸个数中最大数,最小数等也应该灵活运用迭代方法.如:e1=ab?a:b(求两个数中较大数)e2=ce1?c:e1(求三个数中最大数)=c(ab?a:b)?c:(ab?a:b)对于de2?d:e2,将e2代入可求四个数中最大数学习要注意方法,学习要注意抽象,学习要注意应用.,2023/1/7,华中科技大学计算机学院,35,例9.15 任意位数的超长数据的加法运算。

20、,#include stdio.h“(演示EX9_15)#include ctype.h#define N 20/*N表示参与运算数据最长的长度*/void shift(int*a,int n);void shift(int*a,int n)int k,len,sft;len=N-1-n;/*数据的长度*/sft=N-len;/*右对齐移位的位数*/for(k=0;klen;k+)/*右对齐移位*/*(a+k)=*(a+k+sft);for(k=len;kN;k+)/*右对齐移位的位数*/*(a+k)=0;/*对没有存放数据的位填充零*/,2023/1/7,华中科技大学计算机学院,36,求:1

21、2345678901234567+98765432109876543void main(void)int xN,yN,zN+1,i,carry=0,flag;for(i=0;i=0/*数据长度小于N,右对齐移位*/,2023/1/7,华中科技大学计算机学院,37,for(i=0;i=0;i-)/*输出结果。和中的前导字符0不输出*/if(flag=0,2023/1/7,华中科技大学计算机学院,38,2以指针变量为数组首地址时一维数组的指针表示,一般的,为了用指针变量表示数组中的元素,应该先声明一个数组,再声明一个与数组名类型相同的指针变量,然后通过初始化或者赋值操作使指针变量值向数组中的元素。

22、这样就可以指针变量来快速访问数组中的其他元素。例如,先声明指针变量,然后通过赋值语句将数组的起始地址赋给指针变量,使指针变量指向数组中下标为0的元素。int a6,*p;p=a;或者p=一般地,此时称指针变量p指向数组a。,2023/1/7,华中科技大学计算机学院,39,例9.16 显示输出指向数组a的指针变量p的地址、值,数组名a的值,a0的地址。数组a中每个元素的地址和值,以及p依次指向数组中各个元素时的取值和所指元素的值。,#include stdio.hvoid main(void)int i,a5=1,2,3,4,5,*p=a;printf(address of p is%pn,运行

23、结果见P272,2023/1/7,华中科技大学计算机学院,40,3.指向数组元素的指针变量的运算操作,指向数组的指针变量的运算操作可以分为三类。一是对指针变量或由指针变量组成的地址表达式进行运算,目的是快速定位到数组中的指定元素。二是间访操作,即访问指针变量或由指针变量组成的地址表达式所指向的数组元素。三是对间访后的数组元素施行运算。这些运算中往往涉及+和*操作,+和*操作在C中位于第二优先级,结合性是右结合,当两者同时出现的时候需要严格通过结合性来进行分析判断。,2023/1/7,华中科技大学计算机学院,41,设有说明:char s20,*pc;对于字符指针pc,下面的操作合法:,pc=s对

24、字符指针变量pc赋值,使其指向字符数组s(即s0).pc+i 结果为pc后面第i个元素的地址。*(pc+i)结果为pc后面第i个元素。*+pc 结果为pc加1之后所指元素。+*pc 结果为pc所指元素加1。*pc+结果为pc所指元素,然后pc加1。(*pc)+结果为pc所指元素,然后pc所指元素加1。&pc 结果为字符指针变量pc的地址,类型为char*,2023/1/7,华中科技大学计算机学院,42,对于数组名s,下面的操作合法:s+i 结果为数组s中第i个元素的地址(即si的地址)。*(s+i)结果为数组s中第i个元素si。+*s 结果为元素s0加1。(*s)+结果为元素s0的值,然后s0

25、加1。由于数组名s是地址常量,因此下面的操作非法:s=pc 非法.数组名s是地址常量,不能进行赋值操作。&s 非法.数组名s是地址常量,不能取地址。*+s 非法.不能对数组名s进行前缀+操作。*s+非法.不能对数组名s进行后缀+操作,2023/1/7,华中科技大学计算机学院,43,9.4.2 一维数组参数的指针表示 一维数组参数的指针表示是讨论在定义函数时如何用指针表示函数的形参,以及在调用函数时如何用指针表示函数的实参。对于形如int f(int a)的函数,调用时应该用一个整型数组x的数组名x,或者数组打头元素的地址&x0作为实参。数组名x和打头元素的地址&x0的类型都是int*。所以,一

26、维数组作为函数的参数时,形参和实参的类型都应该是数组元素类型的指针。因此,可以用数组元素类型的指针变量来表示形参和实参。,2023/1/7,华中科技大学计算机学院,44,例9.17 用指针变量表示一维数组参数,计算两个向量的数量积(向量的数乘)。见P274,#include stdio.h#define SIZE 3double scalar(double*a,double*b,int n);void main(void)double xSIZE,ySIZE,*px,*py;for(px=x;pxx+SIZE;px+)/*x+SIZE是元素xSIZE的地址*/scanf(%lf,px);get

27、char();for(py=y;py,2023/1/7,华中科技大学计算机学院,45,9.4.3 用指向数组基本元素的指针表示多维数组用指向数组基本元素的指针变量访问数组元素指:如果数组基本元素的数据类型为T,则指向数组基本元素的指针的数据类型为T*。一旦该指针指向了一个对应数组的元素,就可以(象用数组名一样来?)用该指针来表示数组元素。同时对该指针还可以施行运算,使它指向数组中的其它元素。对于二维整型数组uMN,设有声明:int*p=则其vijk元的地址可以写成(p+i*M*N+j*N+k)。而用指针p间访其vijk元的形式为:*(p+i*M*N+j*N+k)。,2023/1/7,华中科技大

28、学计算机学院,46,例9.18 用指向数组基本元素的指针变量实现三维数组元素的输入和输出。,#include“stdio.h”见P274#define I 2#define J 3#define K 4void main(void)int vIJK,*p,n=1;int i,j,k;p=,2023/1/7,华中科技大学计算机学院,47,9.5 指针数组,9.5.1 指针数组的声明及使用1.指针数组的声明声明指针数组的一般形式是:cv T*cv 标识符常量表达式=初值表;其中,T是数据类型,表示数组元素为T类型的指针,可以指向T类型的变量。cv是const、volatile或者const vol

29、atile,它是可选项。标识符是指针数组名。常量表达式是指针数组的大小。“=初值表”是可选项,用于初始化指针数组。,2023/1/7,华中科技大学计算机学院,48,char*pstr2=123,456;该声明语句说明pstr是一个有2个元素的字符指针数组。其中,p0指向字符串123,p1指向字符串456,p0和p1的类型都是char*。例如声明语句:const int x=1,y=2;const int*ps2;ps0=它说明p是一个指向常量字符串的字符型常量指针数组。此时,p的元素本身不能修改,p的元素所指对象也不能修改。,2023/1/7,华中科技大学计算机学院,49,例9.19 理解指针

30、数组含义的编程举例。见P277,#include stdio.hvoid main(void)int x=1,y=2,z=3,i;int*p3;p0=,2023/1/7,华中科技大学计算机学院,50,2.指针数组的使用1)指针数组元素的引用指针数组的引用指对指针数组中元素的引用。对指针数组中元素可以进行同类型指针允许的全部操作。对指针数组中的元素可以赋值、间访、以及施行指针运算。例如:int a=1,2,3,b=4,5,6,*p2;则可:p0=a;p1=b;*p0=12;+*p1;*p1+2)指针数组要先赋值,后使用解释p279 例9.20-例9.23 自学:例9.24,2023/1/7,华中

31、科技大学计算机学院,51,9.5.2 多重指针 指针p由于占用存储单元而有自己地址,因此也可以被另外的指针pp指向。同时,指针pp同样可以被另一个指针ppp所指向。这样就形成了多重指针的概念。如果p是指向T类型变量的指针,则p的地址或存储p的地址的变量pp被称为T类型的双重指针或T类型的二级指针。类似,ppp则被称为T类型的三重指针或T类型的三级指针。一般的,在重数大于1的情况下,n重指针就是以n-1重指针变量的地址为其值的指针变量。,2023/1/7,华中科技大学计算机学院,52,声明一个T类型的n重指针的一般形式为:T*p;“*”表示有n颗“*”,p是T类型的n重指针。void main(

32、void)int x=12345,*p=,2023/1/7,华中科技大学计算机学院,53,*9.6 带参数的main函数,9.6.1 命令行参数命令行参数(command-line arguments)指在操作系统环境下执行一个程序时所提供的参数。例如在DOS环境下的c:copy abc.txt def.txt就是一个命令行 声明具有命令行参数的main函数的一般形式是:类型 main(int argc,char*argv)/函数体,2023/1/7,华中科技大学计算机学院,54,例9.26 回显命令行参数并显示命令行参数个数的程序实例。#include stdio.hvoid main(in

33、t argc,char*argv)int n=0;while(nargc)printf(“%s”,argvn);(nargc-1)?printf():printf(“n”);n+;printf(the number of command-line arguments are%dn,argc);getchar();视情况介绍例9.27,例9.28,2023/1/7,华中科技大学计算机学院,55,设编译连接之后,可执行程序的名字为showC:show I like C programming.,显示:show I like C+programming.the number of command-l

34、ine arguments are 5,2023/1/7,华中科技大学计算机学院,56,9.7 函数的指针,9.7.1 函数指针的声明声明函数指针的一般形式是:类型(*函数指针名)(形参表);其中,(*函数指针名)表示括号内的标识符是一个函数指针。类型则表示函数指针所指函数的返回类型,形参表表示函数指针所指函数的形式参数的类型与个数。函数指针要通过初始化或赋值使其指向特定的函数,然后才能通过函数指针来调用它所指的函数。对函数指针赋值的一般形式是:函数指针名=函数名;,2023/1/7,华中科技大学计算机学院,57,例9.29 函数指针的应用举例。#include stdio.hvoid f1(

35、int x)printf(function f1 is called!n);printf(x=%dn,x);void f2(int x,int y)printf(function f2 is called!n);printf(x=%dty=%dn,x,y);,2023/1/7,华中科技大学计算机学院,58,void main(void)void(*pf1)(int x);void(*pf2)(int x,int y);pf1=f1;pf2=f2;pf1(5);pf2(10,20);(*pf1)(50);(*pf2)(100,200);,2023/1/7,华中科技大学计算机学院,59,自学部分:

36、*9.7.2 函数指针的应用例9.30 读取从键盘输入正文,再将正文以行为单位排序后输出。通过命令行参数-n决定排序方法。如果有命令行参数-n,则将输入行按照数值大小进行排序;否则将按照字典顺序排序。*9.7.3 利用函数指针求开普勒方程的近似根,2023/1/7,华中科技大学计算机学院,60,9.8 指针函数,在C语言中,函数返回的只能是值。这个值可以是一般的数值,也可以是某种类型的指针值。如果函数的返回值是指针类型的值,该函数称为指针函数。如果函数的返回值是T*类型的指针值,该函数称为T类型的指针函数。9.8.1 指针函数的声明与定义声明指针函数原型的一般形式是:类型*函数名(形参表);如

37、:char*strcpy(char*t,char*s);声明函数strcpy是一个字符指针函数。即:该函数的返回值是字符指针。,2023/1/7,华中科技大学计算机学院,61,9.8.2 指针函数的使用 利用指针函数返回的指针,可以对返回的指针所指向的对象进行进一步的操作。如果该指针指向一个数组,实际就间接解决了函数返回多值的问题。例9.32 查找子串的指针函数应用举例。#include stdio.hchar*strstr(char*,char*t);void main(void)char s1=abcdefghijk,s2=fgh,*p;p=strstr(s1,s2);printf(%pt

38、%sn,2023/1/7,华中科技大学计算机学院,62,char*strstr(char*s,char*t)char*ps=s,*pt,*pc;while(*ps!=0)for(pt=t,pc=ps;*pt!=0,2023/1/7,华中科技大学计算机学院,63,*9.9 指向数组的指针,9.9.1 指向数组的指针的声明与定义 指向数组的指针又称为数组的指针。数组的指针是指:指针指向的是一个数组,而非指向数组中的基本元素。对于常用的整型二维数组和指针p和p1,有声明:int u23,*p=&u00,(*p1)3=u;此时,p是指向二维数组中的基本元素u00的指针。p+之后,p将指向二维数组中的基

39、本元素u01。指针p加1操作引起的地址增量是sizeof(int)。(p1的解释接下页),2023/1/7,华中科技大学计算机学院,64,p1是指向有3个元素的一维整型数组的指针。p1的值为第0行(行标为0)的起始地址;p1+后,p1的值为第1行(行标为1)的起始地址。指针p1加1操作引起的地址增量是3sizeof(int)。,p和p1,p1+1,p+1,2023/1/7,华中科技大学计算机学院,65,一般的,设I,J,K,N都是通过#define定义过的n个符号常量,则指向基本元素类型为T的n-1维数组的指针p的说明是:T(*p)JKN;使p指向类型为T的n维数组u的一般形式是:T uIJK

40、N,(*p)JKN=u;例如,对于三维整型数组有:int v234,(*p2)34=v;,2023/1/7,华中科技大学计算机学院,66,建立了上面的指向关系之后,凡是可以用数组名u的场合,都可以用指针p1代替;同理,凡是可以用数组名v的场合,都可以用指针p2代替。当0 i 1,0 j 2,0 k 3时,uij和ui分别可以用p1ij和 p1i表示;vijk,vij,vi分别可以用p2ijk,p2ij,p2i表示。此时,数组名和指针名可以互换使用.,2023/1/7,华中科技大学计算机学院,67,9.9.2 用数组名间访多维数组的元素(可不讲)在C语言中,数组在实现方法上只有一维的概念。一个n

41、维数组被看成以它的下一级n-1维数组为元素的一维数组。设I,J,K,N都是通过#define定义过的n个符号常量,则 int AIJKN;说明的IJKN的n维整型数组,其数组A被看成以I个JKN的n-1维整型数组为元素的一维数组。,2023/1/7,华中科技大学计算机学院,68,A是一个指向n-1维整型数组的常量指针(即不能做左值),*A则表示A所指向n-1维整型数组。因此,以n-1维数组为元素的一维数组就是n维数组。这种方法可以递归的理解。即:以n-2维数组为元素的一维数组就是n-1维数组,,以一维数组为元素的一维数组就是二维数组,直到以基本类型的变量为元素而组成的一维数组。,2023/1/

42、7,华中科技大学计算机学院,69,n维数组可以逐级的分解为以n-1维数组为元素的一维数组。n维数组的数组名是一个指向n-1维数组的常量指针,其值为n维数组的首地址,类型为n-1维数组类型的指针。虽然n维数组可以看成以n-1维数组为元素的一维数组。但在实现上这个一维数组的每个元素都是指向n-2维数组的指针。即A0,A1,AI-1都是指向KN的n-2维数组的指针,其值表示n-1维数组的首地址,其类型是int(*)KN。,2023/1/7,华中科技大学计算机学院,70,自学部分:*9.9.3 用指向数组的指针表示多维数组 多维数组的指针表示是讨论如何用间访操作符*来访问数组元素。由于n维数组去掉最右

43、边一维,最右边二维,,直至数组名分别都是指向基本元素,指向一维数组,直至指向n-1数组的非左值常量指针;同时,还可以定义指向基本元素,指向一维数组,直至指向n-1数组的指针变量;从而使得C语言中关于数组的指针表示内容丰富多彩,形式多种多样。,2023/1/7,华中科技大学计算机学院,71,9.9.4 多维数组参数的指针表示多维数组作为函数参数时,是将实参数组的地址(一般是起始地址)传递给形参。形参一般说明为指向数组元素的指针,或说明为指向下一级数组的指针。但从原理上讲,形参声明为指向下二级数组的指针,指向下三级数组的指针等都可以,只是实参的类型必须与形参的类型一致。,2023/1/7,华中科技

44、大学计算机学院,72,1.形参为指向数组元素的指针 形参说明为指向数组元素的指针时,实参应为数组元素的地址,或为指向数组元素的指针变量。void fun(int*p,int n);/*函数说明,形参说明为指向数组元素的指针*/以实参为数组元素的地址调用fun函数:int u23,v234;fun(u0,2*3);/*u0是u00的地址*/fun(v00,2*3*4);/*v00是元素v000的地址*/,2023/1/7,华中科技大学计算机学院,73,以实参为指向数组元素的指针变量调用fun函数:int u23,v234,*p;p=/*函数调用,p指向元v000*/,2023/1/7,华中科技大

45、学计算机学院,74,2.形参为指向下一级数组的指针 形参为指向下一级数组的指针时,实参应为数组名或指向下一级数组的指针。例如:void f1(int(*p1)3,int n);/*指向一维数组的指针p1为形参*/void f2(int(*p2)34,int n);/*指向二维数组的指针p2为形参*/,2023/1/7,华中科技大学计算机学院,75,以实参为数组名调用f1函数和f2函数:int u23,v234;f1(u,2*3);/*调用函数f1,数组名u作为实参*/f2(v,2*3*4);/*调用函数f2,数组名v作为实参*/以实参为指向下一级数组的指针调用f1函数和f2函数:int u23

46、,v234,(*p1)3,(*p2)34;p1=u;f1(p1,2*3);/*以指向一维数组的指针p1为实参*/p2=v;f2(p2,2*3*4);/*以指向二维数组的指针p2为实参*/,2023/1/7,华中科技大学计算机学院,76,例9.36 日期转换问题。输入一个年、月、日表示的日期,将其转换为该年的第几天。如果输入某年的第几天,将其转换为该年某月某日并输出。此题视情况讲解,2023/1/7,华中科技大学计算机学院,77,*9.10 用指针编写字符串操作函数,9.10.1 字符指针与字符串在C语言中,字符数组主要用于构造字符串。字符串常量在存储方面也完全与字符数组的存储方式相同。字符串是

47、一维字符数组,可以用指向一维字符数组的字符指针来访问和操纵字符串.用指针访问字符数组元素首先需要声明字符指针变量,通过初始化或者赋值使字符指针变量指向字符串,然后就可以通过字符指针来访问字符串中对应的字符。,2023/1/7,华中科技大学计算机学院,78,程序中字符串的表示概括起来有下面几种方法。(1)声明一个字符数组并对其初始化形成字符串,通过数组名和下标引用字符串和字符。,例如:char str80=This is a string.;其中,字符数组str占80个字节,最多可存储79个字符,必须为字符串的终结符0保留一个字节的存储空间。字符串常量This is a string.是初值。,

48、2023/1/7,华中科技大学计算机学院,79,(2)先声明一个字符数组,调用字符串输入函数对其赋值形成字符串,再通过数组名和下标引用字符串和字符。,例如:char str80;gets(str);/*输入This is a string.*/str0=t;其中,字符数组str占80个字节,最多可存储79个字符,必须为字符串的终结符0保留一个字节的存储空间。,2023/1/7,华中科技大学计算机学院,80,(3)声明一个字符指针变量并初始化,通过字符指针变量使用下标或间访操作访问字符串或字符(建议尽量不用此方法)。如声明:char*s=This is a string.;先声明字符指针变量s(

49、简称字符指针),再用字符串This is a string.的起始地址,即字符T的地址初始化s,使s指向字符在内存中连续存放的This is a string.字符串。通过s2=a;*(s+3)=t;则将字符串改为That is a string.。因此,一旦字符指针s指向了字符串,s就可以象数组名一样的使用,用来访问和操纵它所指向的字符串。,2023/1/7,华中科技大学计算机学院,81,(4)声明一个字符数组和一个字符指针变量,并使字符指针指向字符数组。此时既可以通过数组名和下标,也可以通过字符指针、下标或间访操作符*来实现对字符串或字符的访问和操纵。如声明:char str80,*ps=

50、str;它先说明了有80个字节的字符数组str,接着说明一个字符指针变量ps,并且用字符数组的起始地址str(数组名就是数组的起始地址)对其进行初始化,使ps指向字符数组str。,2023/1/7,华中科技大学计算机学院,82,9.10.2 字符串函数的实现,下面根据ISO/IEC 9899:1999(E)中头文件string.h中关于字符串函数规定来实现常用的字符串函数;然后将它们做成为自己的库文件mystring.lib,使得在其他程序中可以直接使用这些函数。同时,通过这种方法,也可以使自己写的代码供他人使用。1.解释p303 头文件mystring.h2.解释p304-p306各字符串操

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号