指针与指针变量

上传人:仙*** 文档编号:244202164 上传时间:2024-10-03 格式:PPT 页数:94 大小:493.50KB
收藏 版权申诉 举报 下载
指针与指针变量_第1页
第1页 / 共94页
指针与指针变量_第2页
第2页 / 共94页
指针与指针变量_第3页
第3页 / 共94页
资源描述:

《指针与指针变量》由会员分享,可在线阅读,更多相关《指针与指针变量(94页珍藏版)》请在装配图网上搜索。

1、单击此处编辑母版标题样式,,单击此处编辑母版文本样式,,第二级,,第三级,,第四级,,第五级,,*,C,语言程序设计教程,*,第8章 指针,,8.1 指针与指针变量,,8.2 指针与函数,,8.3 指针与数组,,8.4 指针与字符串,,8.5 指针数组与命令行参数,,8.6 程序举例,第 8 章 指针,C,语言程序设计教程,10/3/2024,1,,C,语言程序设计教程,8.1 指针与指针变量,8.1.1 指针的概念,,1.内存与变量地址,,内存地址:,内存是计算机用于存储数据的存储器,以一个字节作为存储单元,为了便于访问,给每个字节单元一个唯一的编号,第一字节单元编号为0,以后各单元按顺序

2、连续编号,这些单元编号称为内存单元的地址 。,,变量地址:,变量所分配存储空间的首字节单元地址(字节单元编号),。,10/3/2024,2,,C,语言程序设计教程,2. 变量的三要素:,名字、类型与值,,每个变量都通过,变量名与相应的存储单元相连系,,具体分配哪些单元给变量,由C编译系统完成变量名到对应内存单元地址的变换。,,,变量分配存储空间的,大小,由,类型,决定。,,变量的值,则是指相应,存储单元的内容,。,,,3.,内存存取方式,,直接存取,:把直接按变量名或地址存取变量值的方式称为 “直接存取”方式。,,间接存取,:通过定义一种特殊的变量专门存放内存或变量的地址,然后根据该地址值再去

3、访问相应的存储单元,。,10/3/2024,3,,C,语言程序设计教程,系统为特殊变量,p(,用来存放地址的)分配的存储空间地址是4800,,p,中保存的是变量,a,的地址,即4000,当要读取,a,变量的值12345时,不是直接通过,a,变量,也不是直接通过保存12345的内存单元的地址4000去取值,而是先通过变量,p,得到,p,的值4000,即,a,的地址,再根据地址4000读取它所指向单元的值12345。,这种间接的通过变量,p,得到变量,a,的地址,再存取变量,a,的值的方式即为“间接存取”。,,,通常称变量,p,指向变量,a,,变量,a,是变量,p,所指向的对象,…,4000,12

4、345,4000,,4002,4800,p,a,p(4800),,p(4800),,a(4000),,4000,12345,4000,间接存取示意图,10/3/2024,4,,C,语言程序设计教程,4.指针的概念,在C语言中,用,指针,来表示一个变量指向另一个变量这样的指向关系。,,所谓指针即地址。,,一个变量的指针即该变量的地址,如4000就是指向变量,a,的指针。,,,指针变量,:专门存放地址的变量,如,p,即是一个指针变量,它存放的,是,a,的地址4000。,10/3/2024,5,,C,语言程序设计教程,8.1.2 指针变量的定义与初始化,,1. 指针变量的定义,,,类型标识符

5、*指针变量名;,,例:,float *p1;,(,定义,p1,为,指向实型变量的指针变量,),,,char *p2;,(,定义,p2,为,指向字符型变量的指针变量,),,在指针变量定义中,*是一个说明符,它表明其后的变量是指针变量,如,p,是指针变量,而不要认为“*,p”,是指针变量。,,指针变量定义时指定的数据类型不是指针变量本身(变量存放的值)的数据类型,而是指针变量所指向的对象(或称目标)的数据类型,,,指针变量存放的是所指向的某个变量的地址值,而普通变量保存的是该变量本身的值,,,指针变量并不固定指向一个变量,可指向同类型的不同变量,10/3/2024,6,,C,语言程序设计教程,

6、(1),指针运算符与地址运算符,,,与指针引用有关的两个运算符:&与*。,,,&:取地址运算符,,,,*:指针运算符,或称指向运算符、间接访问运算 符。,,指针指向的对象的表示形式:,,*指针变量,,此处*是访问指针所指对象的运算符,与指针定义时的*不同。,2. 指针变量初始化,,10/3/2024,7,,C,语言程序设计教程,(,2) 指针变量初始化,若有定义:,,,int,a,*p;,,语句仅仅定义了指针变量,p,,但指针变量并未指向确定的变量(或内存单元)。因为这些指针变量还没有赋给确定的地址值,只有将某一具体变量的地址赋给指针变量之后,指针变量才指向确定的变量(内存单元)。,,指针变

7、量初始化:,在定义指针时同时给指针一个初始值,,如:,int,a,*p=,4000,3,a(4000),pa,*pa,10/3/2024,8,,C,语言程序设计教程,(3) 指针变量的引用,,① *指针变量名——代表所指变量的值。,,,② 指针变量名——代表所指变量的地址。,,有定义:,int,a,*p=,,用*,p,来表示,p,指向的对象,a,*p,与,a,是等价的。,,*,p,可以象普通变量一样使用。 例如:,,,a=12;,,*p=12;,,,scanf,("%d",,scanf,("%d",p);,,,printf,(,“,%d%d,”,,*p,a);,,注意,:,*,与,&

8、,具有相同的优先级,,结合方向从右到左,。这样,,&*,p,即,&(*,p),,是对变量,*,p,取地址,它与,&,a,等价;,p,与,&(*,p),等价,,a,与,*(&,a),等价。,,10/3/2024,9,,C,语言程序设计教程,例,,,main(0,,{,int,a=100,b=10,*p1,p2;,,p1=,,printf,(,“,%d,%d,%d,%d\n,”,,a,b,*p1,*p2);,,},10/3/2024,10,,C,语言程序设计教程,,例 输入,a,b,两个整数,按从大到小顺序输出。,,main(),,{,int,*p1,*p2,*p,a,b;,,scanf,(,“

9、,%d,%d,”,,,,p1=,,if(a

10、在,a,可以出现的任何位置.,,,*,与&的说明:设,int,a=1,*p;p=,,①&*p,,,从左向右结合,相当于&,a,,②*&a,,,先取,a,的地址,再进行*运算,即指向&,a,所指向的变量,相当于,a,,③(*p)++,,,相当于,a++,10/3/2024,12,,C,语言程序设计教程,,例 从键盘输入三个整数,要求设三个指针变量,p1,p2,p3,,使其分别从大到小指向三个整数,然后输出。,,main(),,{,int,*p1,*p2,*p3,i,j,k,temp;,,scanf,(,“,%d,%d,%d,”,,,,p1=,,if(_____ ){temp=*p1;______

11、__;__________;},,if(_____){temp=*p1;________;_________;},,if(_ ___){temp=*p2;_________;_________;},,printf,(,“,%d%d%d,”,,*p1,*p2,*p3);,,},10/3/2024,13,,C,语言程序设计教程,8.1.3 指针运算,1. 指针的赋值运算,,(1)将变量地址值赋给指针变量,使指针指向该变量。,,设有如下定义:,,,int,a,b,*pa,*,pb,;,,,float *pf;,,第一行定义了整型变量,a,b,及指针变量,pa,,pb,。pa、,pb,还没有被赋值,

12、因此,pa、,pb,没有指向任何变量, 下面语句完成对,pa,,pb,的赋值:,,,pa=,,pb,=,,10/3/2024,14,,C,语言程序设计教程,例如,:,,int,j,k;,,,int,*pointer1,*pointer2;,,,pointer1=,,pointer2=,pointer1,j,pointer2,k,10/3/2024,15,,C,语言程序设计教程,(2) 相同类型的指针变量间的赋值,,pa,与,pb,都是整型指针变量,它们间可以相互赋值,如:,pb,=pa;,即,pa,,pb,都指向变量,a,,此时,a、*pa、*,pb,是等价的。指针指向变化如下图:,注意,:只

13、有相同类型的指针变量才能相互赋值,如,pf=pa;,是不允许的。因为,pa,是整型指针,,pf,是浮点型指针。,&a,&b,pa,pb,a,*pa,b,*,pb,&a,&a,pa,pb,a,*pa,*,pb,b,10/3/2024,16,,C,语言程序设计教程,(3),给指针变量赋,空值,给指针变量赋,空值,,说明该指针不指向任何变量。,,“空”指针值用,NULL,表示,,NULL,是在头文件,stdio,.h,中预定义的常量,其值为0,在使用时应加上预定义行,如:,,#,include ",stdio,.h",,,int,*pa=NULL;,,,,亦可以用下面的语句给指针赋“空值”:,,,,

14、a=0;,,,或:,pa=,’,\0,’,;,,,这里指针,pa,并非指向0地址单元,而是具有一个确定的“空值”,表示,pa,不指向任何变量。,,注意,:,指针虽然可以赋值0,但却不能把其它的常量地址赋给指针。例如:,pa=4000;,是非法的,。,10/3/2024,17,,C,语言程序设计教程,例 8.1 指针定义与初始化,main(),,{,int,a,b;,,int,*pointer_1,*pointer_2;,,a=100;b=10;,,pointer_1=,,pointer_2=,,,printf,("%d,%d\n",a,b);,,printf,("%d,%d\n",*poin

15、ter_1,*pointer_2);,,},10/3/2024,18,,C,语言程序设计教程,程序运行结果:,,100,10,,100,10,&a,&b,b,Pointer_1,Pointer_2,a,*pointer_1,*pointer_2,10/3/2024,19,,C,语言程序设计教程,例8.2 从键盘上输入两个整数到,a、b,,按由大到小输出。,#,include <,stdio,.h>,,main( ),,{,int,a,b,*pa=&a,*,pb,=/*,定义指针变量,pa、,pb,,,如下页图,a*/,,,scanf,(″%d%d″,,,if (*pa<*,pb,) { p=

16、pa; /*,进行指针交换,如下页,图,b,c*/,,pa=,pb,;,,,pb,=p;,,},,printf,(″\n a=%d,b=%d\n″,a,b);,,printf,(″\n max=%d,min=%d″,*pa,*,pb,);,,/* pa,指向大数,,pb,指向小数*/,,},10/3/2024,20,,C,语言程序设计教程,若输入:,12 22↙,输出结果:,a=12,b=22 max=22,min=12,(,b),,(c),,指针变化示意图,12,,,,22,p,,pa,,pb,12,,,22,p,,pa,,pb,,

17、pa,,pb,a,b,10/3/2024,21,,C,语言程序设计教程,2. 指针的算术运算,(1) 加减运算,:,一个指针可以加、减一个整数,n,,其结果与指针所指对象的数据类型有关。指针变量的值应增加或减少“,n×,sizeof,(,指针类型)”。,,,加减运算常用于数组的处理,。,对指向一般数据的指针,加减运算无实际意义。例如: ,,,int,a[10],*p=a,*x; ,,x=p+3; /*,实际上是,p,加上3*2个字节赋给,x, x,指向数组的第三个分量*/,,对于不同基类型的指针,指针变量,“,加上,”,或,“,减去,”,一个整数,n,所移动的字节数是不同的。例如: ,,

18、,float a[10], *p=a, *x; ,,p=p+3; /*,实际上是,p,加上3*4个字节赋给,x, x,依然指向数组的第三个分量*/,10/3/2024,22,,C,语言程序设计教程,(2) 自增自减运算,指针变量自增、自减运算具有上述运算的特点,但有前置后置、先用后用的考虑,务请小心。 例如: ,,,int,a[10], *p=a, *x; ,,x=p++; /* x,第一个元素分量,,p,指向第二个元素*/,x=++p; /* x、 p,均指向数组的第二个分量*/,,*,,p++,相当于*,(,p+ +)。,,*(p++),与(*,p)++,含义不同,前者表示,

19、地址自增,,后者表示,当前,所指向的数据自增,。,10/3/2024,23,,C,语言程序设计教程,2.,*&,a,的含意是什么?,,(答:,a,),,3.,(*p)++,相当于什么?,,(答:,a++,),思考:,,1.若有定义,int,a,*p;,,执行了,“,p=&a”,,则: “&*,p”,的含意是什,么?,(答:,相当于&,a,),10/3/2024,24,,C,语言程序设计教程,3.,指针的关系运算,,与基本类型变量一样,指针可以进行关系运算。,,在关系表达式中允许对两个指针进行所有的关系运算。若,p,q,是两个同类型的指针变量,则:,p>q,p=q,都是允许的。,,指针的关系运

20、算在指向数组的指针中广泛的运用,假设,p、q,是指向同一数组的两个指针,执行,p>q,的运算,其含义为,若表达式结果为真(非0值),则说明,p,所指元素在,q,所指元素之后。或者说,q,所指元素离数组第一个元素更近些。,,,注意:在指针进行关系运算之前,指针必须指向确定的变量或存储区域,即指针有初始值;另外,只有相同类型的指针才能进行比较。,,10/3/2024,25,,C,语言程序设计教程,8.1.4 多级,指针,,把指向指针型数据的指针变量称为指向指针的指针,或,称多级指针,。,,二级指针的定义形式如下:,,,数据类型 **指针变量,,例如:,,,int,a,*p,**pp;,,a=2

21、2;,,p=,,pp=,,假设变量,a,的地址为4000,指针,p,的地址为4100,二级指针,pp,的地址为4800。,a、p、pp,三者的关系如上图。,&p=4100,&a=4000,22,pp(4800) p(4100) a(4000),10/3/2024,26,,C,语言程序设计教程,8.2 指针与函数,8.2.1 指针作为函数参数,,利用指针作函数参数,可以实现函数之间多个数据的传递,当形参为指针变量时,其对应实参可以是指针变量或存储单元地址。,,函数形参为指针变量,用,指针变量,或,变量地址,作实参,,,例8.3 编写一个交换两个变量的函

22、数,在主程序中 调用,实现两个变量值的交换。,10/3/2024,27,,C,语言程序设计教程,程序如下:,#,include<,stdio,.h>,,main(),,{,int,a,b;,,,int,*pa,*,pb,;,,void swap(,int,*p1,,int,*p2); /*,函数声明*/,,,scanf,(″%d%d″,,,pa=,,/* pa,指向变量,a */,,,pb,=,,/*,pb,指向变量,b */,,swap(pa,,pb,);,,printf,(″\,na,=%d,b=%d\n″,a,b);,,},或:,swap(,10/3/2024,28,,C,语

23、言程序设计教程,接上页:,void swap(,int,*p1,,int,*p2),,{,int,temp;,,temp=*p1; /*,交换指针,p1、p2,所指向的变量的值*/,,*,p1=*p2;,,,*p2=temp;,,},程序运行结果如下:,,输入:,12 22↙,,输出:,a=22,b=12,10/3/2024,29,,C,语言程序设计教程,分析以下,swap,函数能否实现交换:,,swap(,int,*p1,,int,*p2),,{,int,*p;,,*p=*p1;,,*,p1=*p2;*p2=*p;},,,,,swap(,int,x,,int,y),,{,int,t;t=x

24、,x=y;y=t;},,由于*,p,并不指向某一个变量,即其中的地址并不确定,可能造成系统破坏,由于函数的“值传递”,虽然交换了变量,x,y,的值,但并不能改变,a,b,的值。,10/3/2024,30,,C,语言程序设计教程,两点说明:,,(1) 若在函数体中交换指针变量的值,实参,a、b,的值并不改变,指针参数亦是传值。 例如:,,,int,*p; ,,p=p1; p1=p2; p2=p; ,,,不要希望如此完成处理。 ,,(2) 函数中交换值时不能使用无初值的指针变量作临时变量。 例如: ,,,int,*p; ,,*p=*p1; *p1=*p2; *p2=*p; ,,p,无

25、确定值,对,p,的使用可能带来不可预期的后果。,10/3/2024,31,,C,语言程序设计教程,8.2.2 指针函数,指针函数,:是指返回值为指针的函数,,指针函数的定义形式:,,,类型标示符 *函数名(参数),,例如:,,int,*fun(,int,a,,int,b),,{,,,函数体语句,,},,在函数体中有返回指针或地址的语句,形如:,,,return (&,变量名);,,或,return (,指针变量);,,并且返回值的类型要与函数类型一致。,,10/3/2024,32,,C,语言程序设计教程,例8.3 分析如下程序,main( ),,{,int,a,b,*p;,,int,

26、*max(,int,x,,int,y);,,scanf,(“%d,%d”,,,p=max(a,b);,,printf,(“max=%d”,*p);,,},,int,*max(,int,x,,int,y),,{ if x>y) return (,,else return (,,},10/3/2024,33,,C,语言程序设计教程,8.2.3 指向函数的指针,一个函数包括一组指令序列,存储在某一段内存中,这段内存空间的起始地址称为,函数的入口地址,,称函数入口地址为,函数的指针,。,函数名,代表函数的入口地址,,,可以定义一个指针变量,其值等于该函数的入口地址,指向这个函数,这样通过这个指

27、针变量也能调用这个函数。这种指针变量称为,指向函数的指针变量,。,,定义指向函数的指针变量的一般形式为,:,,,类型标识符(*指针变量名)( ),;,,例如:,,,int,(*p)(); /*,指针变量,p,可以指向一个整型函数*/,,,float (*q)(); /*,指针变量,q,可以指向一个浮点型函数*/,10/3/2024,34,,C,语言程序设计教程,刚定义的指向函数的指针变量,亦象其它指针变量一样要赋以地址值才能引用。当将某个函数的入口地址赋给指向函数的指针变量,就可用该指针变量来调用所指向的函数,,,给函数指针赋初值:将函数名(函数的入口地址值)赋给指针变量,,,例

28、如,,int,m, (*p)( );,,,,,int,max(,int,a,,int,b);,,则可以,p=max; /* p,指向函数,max() */,,指针调用函数的,,一般形式为,:,,(,*指针变量)( 实参表),;,,如上例,:,m=(*p)(12,22); /*,比较,m=max(12,22); */,10/3/2024,35,,C,语言程序设计教程,注意:,用函数指针调用函数是间接调用,没有参数类型说明,,C,编译系统也无法进行类型检查,因此,在使用这种形式调用函数时要特别小心。实参一定要和指针所指函数的形参类型一致。,,函数指针可以作为函数参数,此时,当函数指针每次

29、指向不同的函数时,可执行不同的函数来完成不同的功能,,,例 8.4,函数,max(),用来求一维数组的元素的最大值,在主调函数中用函数名调用该函数与用函数指针调用该函数来实现。,10/3/2024,36,,C,语言程序设计教程,程序如下:,#,include ",stdio,.h",,#define M 8,,main(),,{float,sumf,,sump;,,float a[M]={11,2,-3,4.5,5,69,7,80};,,float (*p)(); /*,定义指向函数的指针,p*/,,float max(float a[],,int,n); /*,函数

30、声明*/,,,p=max; /*,函数名(函数入口地址)赋给指针,p*/,,sump=(*p)(a,M); /*,用指针方式调用函数*/,,sumf,=max(a,M); /*,用函数名调用,max(),函数*/,,,printf,("sump=%.2f\n",sump);,,printf,(",sumf,=%.2f\n",,sumf,);,,},10/3/2024,37,,C,语言程序设计教程,程序接上页:,float max(float a[],,int,n),,{,int,k;,,float s;,,s=a[0];,,for (k=

31、0;k

32、的指针,,数组名是一个常量指针,它的值为该数组的首地址,,,1.指向数组的指针的定义方法与指向基本类型变量的指针的定义方法相同,,例如:,,int,a[10]={1,3,5,7,9};,,int,*p;,,p=&a[2],; (,把数组元素,a[2],的地址赋给指针变量,p),,p=a;,(,把数组的首地址赋给指针变量,p),10/3/2024,40,,C,语言程序设计教程,,C,语言规定,:数组名代表数组首地址,是一个地址常量,。,,因此,下面两个语句等价:,,,p=,,p=a;,,在定义指针变量的同时可赋初值:,,,int,a[10], *p= (,或,int,*p=a;),,等价于:

33、,int,*p;,,p=,两句,。,,10/3/2024,41,,C,语言程序设计教程,指向数组的指针变量,p,&a[0],1,3,15,17,19,p,a[0],:,a[9],,p[9],a+0,p+1,,或,a+1,p+9,,或,a+9,*(,a+9),或*(,p+9),,10/3/2024,42,,C,语言程序设计教程,2.通过指针引用数组元素,,,*,p=5;,,表示,对,p,当前所指的数组元素赋以一个值5。,,C,规定:,p+1,指向数组的下一元素(而不是将,p,值简单地加1)。,p+1,意味着使,p,的原值(地址),加,d,个字节(,d,为一个数组元素所占的字节数)。,如果,p,的

34、初值为&,a[0],,则:,,(1,),p+i,和,a+i,就是,a[i],的地址,或者说它们指向,a,数组的第,i,个元素(见下页图)。,,(2)*(,p+i),或,*(,a+i),是,p+i,或,a+i,所指向的数组元素,,即,a[i]。,,(3),指向数组的指针变量也可以带下标,如,p[i],与*,(,p+i)、 a[i],等价 。,10/3/2024,43,,C,语言程序设计教程,*(,p+i),a,数组,a[0],a[1],a[2],a[i],a[9],p,p+1,a+1,p+i, a+i,p+9, a+9,综上所述,引用一个数组元素有二法:,,(1)下标法:如,a[i],形式;,,

35、(2)指针法:如*(,a+i),或 *(,p+i)。,其中,a,是数组名,,p,是,指向数组的指针变量,其初值,p=a。,,10/3/2024,44,,C,语言程序设计教程,main(),,{,,int,a[10];,,int,i;,,for (i=0;i<10;i++),,scanf,("%d",,,printf,("\n");,,for (i=0;i<10;i++),,printf,("%d",,a[i],) ;,,},例8.5 用三种方法输出数组全部元素。,,(1),下标法,10/3/2024,45,,C,语言程序设计教程,main(),,{,int,a[10];,,int,i;,,

36、for (i=0;i<10;i++),,scanf,("%d",,,printf,("\n");,,for (i=0;i<10;i++),,printf,("%d",,*(a+i),);,,},(2),通过数组名计算数组元素地址,输出元素的值,10/3/2024,46,,C,语言程序设计教程,(3),用指针变量指向数组元素,,main(),,{,int,a[10];,,int,*p,i;,,for (i=0;i<10;i++),,scanf,("%d",,,printf,("\n");,,for (,p=a;p<(a+10);p++,),,printf,("%d",,*p,,);,,},三种方

37、法的比较,:,,用,下标法,比较直观,能直接知道是第几个元素;,,而用,指针法,则执行效率更高。,10/3/2024,47,,C,语言程序设计教程,使用指针变量时,应注意:,,(1)指针变量可实现使本身的值改变。,,,P++,合法;但,a++,不合法(,a,是数组名,代表数组首地址,在程序运行中是固定不变的。),,(2)要注意指针变量的当前值。,main(),,{,int,a[10];,,int,*p, i;,,p=a;,,for ( ;p

38、("%d",,*p,);,,},不能&,p,增加:,p=a;,10/3/2024,48,,C,语言程序设计教程,,(3),*,p++,相当于*(,p++),,因为*与++优先级相同,且结合方向从右向左,其作用是先获得,p,指向变量的值,然后执行,p=p+1;,,(4),*(p++),与*(++,p),意义不同,后者是先,p=p+1,,再获得,p,指向的变量值。,,若,p=a,,则输出*(,p++),是先输出,a[0],,再让,p,指向,a[1];,输出*(++,p),是先使,p,指向,a[1],,再输出,p,所指的,a[1]。,,(5),(*p)++,表示的是将,p,指向的变量值+1,10/3

39、/2024,49,,C,语言程序设计教程,1、写出下列程序的执行结果,,#,include<,stdio,.h>,,,main(),,{,,,int,a[]={1,2,3,4,5,6},,,*p=a;,,printf,(,“,%d,”,,(*++p)++);,,},10/3/2024,50,,C,语言程序设计教程,2、写出下列程序的执行结果,,,,#,include<,stdio,.h>,,main(),,{,,,int,a[]={1,2,3,4,5,6},*p=a;,,*(p+3)+=2;,,printf,(,“,n1=%d,n2=%d,”,,*p,*(p+3));,,},10/3/2024

40、,51,,C,语言程序设计教程,3、写出下列程序的执行结果,,#,include<,stdio,.h>,,main(),,{,,,int,a[]={1,3,5,7,9},*p=a;,,printf,(,“,%d\n,”,,(*p++));,,,printf,(,“,%d\n,”,,(*++p));,,,printf,(,“,%d\n,”,,(*++p)++));,,},10/3/2024,52,,C,语言程序设计教程,8.3.2 二维数组与多维数组的指针表示法,1.二维数组的地址,,设有一个二维数 组,a,,它有三行四列:,,,int,a[3][4];,,数组名,a:,代表整个二维数组的首地

41、址,也就是第0行的首地址。,,a+i:,代表第,i,行的首地址。(见下页图),,10/3/2024,53,,C,语言程序设计教程,数组名,a,代表整个二维数组的首地址:,a[0],,a[1],a[2],a,=,=,=,1,9,17,3,11,19,7,15,23,上图,a,数组包含三个元素:,a[0],a[1],a[2].,,而每个元素又,,是一个一维数组,它包含4个元素(即4个列元素),,,如:,a[0],又包含:,a[0][0],a[0][1],a[0][2],a[0][3].,10/3/2024,54,,C,语言程序设计教程,一维数组名,a[i]:,,代表第,i,行的首地址,即第,i,行

42、中第0列元素的地址(既,&,a[i][0])。,,a[i]+j:,,代表第,i,行中的第,j,个元素的地址,即为,&,a[i][j]。,,注意地址变化的单位数值在不同的场合的实际字节数是不同的:,,“,a+1,”,中的,“,1,”,实际代表数组中,一行,元素所占的总字节数;,,“,a[i]+1”,中的,“,1,”,代表数组中一个元素所占的字节数。,,10/3/2024,55,,C,语言程序设计教程,a+2,,a,数组,a[0],a[1],a[2],a,a+1,(,2000),(,2008),(,2016),a,代表,第0行,的首地址,,a+1,代表第1,行,的首地址,,a+2,代表第2,行的首

43、地址.每行存放4个整型数据(即1个元素占2个字节),因此,这里+1的含义是:+4*2=+8个字节.,10/3/2024,56,,C,语言程序设计教程,,,,2000,,1,2002,,3,2004,,5,2006,,7,2008,,9,2010,,11,2012,,13,2014,,15,2016,,17,2018,,19,2020,,21,2022,,23,a,a+1,a+2,a[0]+1,a[0]+2,a[0]+3,行地址,元素地址的表示法,10/3/2024,57,,C,语言程序设计教程,例8.6 用指针表示法输出二维数组的各元素。,#,include<,stdio,.h>,,main(

44、),,{static,int,a[2][3]={{0,1,2,},{3,4,5}};,,int,k,j,*p;,,,for (j=0;j<2;j++),,/*,方式1 */,,{,for (k=0;k<3;k++),,,printf,("%5d",*(a[j]+k));,,,,/* a[j],是,j,行首地址,,a[j]+k,是,j,行,k,列元素的地址*/,,,,putchar,(,‘,\n,’,);,,},,putchar,(,‘,\n,’,);,10/3/2024,58,,C,语言程序设计教程,接上页:,for (j=0;j<2;j++) /*

45、,方式2 */,,{,for (k=0;k<3;k++),,,printf,("%5d",*(*(a+j)+k));,,,/* *(a+j),是,j,行首地址,*(,a+j)+k,是,j,行,k,列元素的地址*/,,,,putchar,(,‘,\n,’,);,,},,p=a;,,/* p,指向数组的第一个元素 */,,,for (j=0;j<2;j++) /*,方式3 */,,{,for (k=0;k<3;k++),,,printf,("%5d",*(p++)); /*,输出,p,所指示的元素 */,,,,putchar,(,‘,\n,’,);,,},,},

46、10/3/2024,59,,C,语言程序设计教程,,,输出的结果是:,,,0 1 2,,3 4 5,,,,0 1 2,,3 4 5,,,,0 1 2,,3 4 5,10/3/2024,60,,C,语言程序设计教程,2.,指向二维数组的指针变量,,有两种情况,:一是直接指向数组元素的指针变量;,,二是指向一个含有,m,个元素的一维数组。,,这两种不同形式的指针变量,其使用方法不同。,,指向数组元素的指针变量,即简单指针变量,如:,,,int,*p,a[3][4];,,p=,,(2),指向由,m,个元素组成的一维数组的指针变量,,定义形式:,类型

47、 (*指针变量)[元素个数],,如:,int,(*p)[4];,,10/3/2024,61,,C,语言程序设计教程,注意:,,(1),int,(*p)[4];,定义,一个指针变量,p ,p,指向包含4个元素的一维数组。,,(2),p+i,与,*(,p+i),的区别:,,,,p+i,是指向第,i,行的指针(第,i,行的首地址);,*(,p+i),是指向第,i,行第1个元素的地址;,,,两者数值相等,但含义不同:,p+i,的增值将以行长为单位,,而,*(,p+i),增值,将以元素长度为单位。,,10/3/2024,62,,C,语言程序设计教程,即:,p+i+1,将指向,第,i,行再下一行的首地

48、址,而,*(,p+i)+1,将,指向第,i,行首元素的下一个元素地址。(见下图),,设,int,a[3][4],(*p)[4];,,p=a;,P,a,P+1,P+2,a[0],a[1],a[2],如果,p,先指向,a[0],,则,p+1,不是指向,a[0][1],,而是指向,a[1],10/3/2024,63,,C,语言程序设计教程,,例8.7,,main( ),,{static,int,a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};,,int,(*p)[4],i,j;,,p=a;,,scanf,("i=%d,j=%d",,,printf,("a[%d][%

49、d]=%d\n", i, j, *(*(p+i)+j) );,,},10/3/2024,64,,C,语言程序设计教程,8.4 指针与字符串,8.4.1 字符串的指针表示法,,,回顾:字符串可以保存在字符数组中,如。,,,main( ),,{static char string[ ]="I Love China!";,,printf,("%,s,\n",string);,,},,运行时输出:,I Love China!,10/3/2024,65,,C,语言程序设计教程,用字符指针指向字符串:,,字符指针变量的定义:,char *,指针变量 ;,,如:,char *p;,,(1),在定义时

50、初始化指针变量使指针指向一个字符串。,,,main( ),,{char *string=“I Love China!” ;,(,初始化,string),,,printf,( "%,s,\n", string );,,},,,运行时也输出:,,,I Love China!,10/3/2024,66,,C,语言程序设计教程,,char *,str,=“I love china”,str1[40];,,等价于下列两句:,,,,char *,str,;,,,str,=“I love china” ;,,,以上语句的含义,:,,,定义,str,为指针变量,它指向,字符型,数据,且赋值语句把字符串,“,

51、I love china ”,的,首地址,赋给了指针变量,str,。,,,对字符串的,整体输出,实际上还是从指针所指示的字符开始逐个显示(系统在输出一个字符后自动执行,p++),,直到遇到字符串结束标志符,‘\0’,为止。而在,输入,时,亦是将字符串的各字符自动顺序存储在,p,指示的存储区中,并在最后自动加上,‘\0,’,。,,Str1=“I love china”; ??,10/3/2024,67,,C,语言程序设计教程,(2)用指针变量来实现对字符串的访问,例8. 8 将一已知字符串第,n,个字符开始的剩余字符复制到另一字符串中。,main(),,{,int,i,n;,,char

52、 a[]="computer";,,char b[10],*p,*q;,,p=a;,,q=b;,,scanf,("%d",,,if (,strlen,(a)>=n) p+=n-1;,,/*,指针指到要复制的第一个字符 */,,,10/3/2024,68,,C,语言程序设计教程,for (;*p!=,'\0',;p++,q++),,*q=*p;,,*q=,'\0',; /*,字符串以,’,\0,’,结尾 */,,,printf,("String a : %s\n",a);,,printf,("String b : %s\n",b);,,},,输入:,3↙,,输出:,computer,,mpu

53、ter,,考虑一下,若输出语句改为如下语句会如何?,,printf,(“string a is :%s\n”,p);,,printf,(“string b is %s\n”,q);,10/3/2024,69,,C,语言程序设计教程,8.4.2 字符串数组,,字符串数组,:是指数组中的每个元素都是一个存 放字符串的数组。,,字符串数组可以用一个二维字符数组来存储,。,,例如:,char,languge,[3] [10];,,数组的第一个下标决定字符串的个数,第二个下标是字符串的最大长度(实际最多9个字符,‘\0’占一位置)。,,可以对字符串数组赋初值。例如:,,char,languge,[3]

54、 [10];={“Basic”, “c++”, “,pascal,”},,10/3/2024,70,,C,语言程序设计教程,综合练习:,,,分别用字符数组和指针变量两种方法将字符串,a,复制到字符串,b,中。,,,10/3/2024,71,,C,语言程序设计教程,用字符数组:,,main(),,{char a[]=,”,i am a boy.,”,,b[];,,,int,i,j;,,for(i=0;a[i]!=‘\0,’,;i++)b[i]=a[i];,,,printf,(,“,string a is:%s\n,”,,a);,,,printf,(,“,string b is :,”,);,,f

55、or(j=0;j

56、tf,(,“,%c,”,,b[i]);,,},,10/3/2024,73,,C,语言程序设计教程,,综合练习:,,,1、写出下列程序的输出结果,,#,include<,stdio,.h>,,void string(char *s),,{static,int,n=0;,int,k;,,k=*s-,‘,0,’,;n+=k;,,printf,(,“,n=%d,*s=%c,s=%s\n,”,,n,*s,s);},,void main(void),,{char a[]=,”,123,”,;,int,k;,,for(k=0;k<3;++k)string(},,10/3/2024,74,,C,语言程序设计教

57、程,2、说明下列各函数的功能:,,char *,strcat,(char *s,char *ct),,{char *t;,,for(t=s;*t;t++);,,while(*t++=*ct++);,,return s;},,,int,n_upper(char *s),,{,int,n;,,for(n=0;*s;s++)if(*s>=,’,A,’,&&*s<=,’,z,’,)++n;,,return n;},10/3/2024,75,,C,语言程序设计教程,3、以下程序运行后,输出结果是,,,main(),,{static char a[]="ABCDEFGH",b[]=",abCDefFh,"

58、;,,char *p1,*p2;,,int,k;,,p1=a; p2=b;,,for(k=0;k<=7;k++),,if (*(p1+k)==*(p2+k)),,printf,("%c",*(p1+k));,,,,,printf,("\n");,,},10/3/2024,76,,C,语言程序设计教程,8.5 指针数组与命令行参数,,,8.5.1 指针数组,,,指针数组:是指针变量的集合。即它的每一个元素都是指针变量,且都具有相同的存储类别和指向相同的数据类型。,,指针数组的定义形式为:,,,类型标识符 *数组名[数组长度说明];,,例如:,,,int,*p[10];,,由于[ ]比*的优先

59、级高,因此,p,先与 [10]结合成,p[10],,而,p[10],正是数组的定义形式,共有10个元素。最后,p[10],与*结合,表示它的各元素可以指向一个整型变量。,10/3/2024,77,,C,语言程序设计教程,指针数组广泛应用于对字符串的处理,,例如有定义:,,,char *p[3];,,定义了一个具有三个元素,p[0],p[1],p[2],的指针数组。每个元素都可以指向一个字符数组,或字符串。,,若利用数组初始化,则:,,char *p[3]= {“Basic”, “c++”, “,pascal,”};,,,P[0],指向字符串“,Basic”;,,P[0],指向字符串,“,

60、c++”;,,P[0],指向字符串,“,pascal,” ;,10/3/2024,78,,C,语言程序设计教程,例8.9 字符指针数组的赋值,,#,define NULL 0,,main( ),,{static char a[ ]=“Fortran”;,,static char b[ ]=“COBOL”;,,static char c[ ]=“Pascal”;,,,int,i;,char *p[4],;,,p[0]=a; p[1]=b; p[2]=c; p[3]=NULL;,,for (i=0;p[i]!=NULL;i++),,,printf,(“Language

61、 %d is %s\n”,i+1,p[i]);,,},10/3/2024,79,,C,语言程序设计教程,例8.10 有若干本书,将书名按字典顺序排序,#,include<,stdio,.h>,,#include,,main(),,{ char *,bname,[]={"Programming in ANSI C","BASIC","Visual C++ 6.0 Programming ","TRUBO C 2.0"};,,int,i,m;,,,,void sort(char *name[],,int,);,,m=,sizeof,(,bname,)/,sizeof,(char *); /*,

62、字符串个数*/,,,sort(,bname,,m); /*,排序,改变指针的连接关系*/,,,printf,("\n");,,for (i=0;i

63、,if (,strcmp,(name[k],name[j])>0) k=j; /*,第,j,个元素更小*/,if (k!=i) /*,最小元素是该趟的第一个元素 则不需交换 */ {,t=name[i];name[i]=name[k];name[k]=t;} } },输出结果为:,,,BASIC Programming in ANSI C TRUBO C 2.0 Visual C++ 6.0 Programming,,10/3/2024,81,,C,语言程序设计教程,注意,: (1)字符数组中每个元素可存放一个字符,而字符指针变量存放

64、字符串首地址,而不是存放在字符指针变量中。 (2)对字符数组,与普通数组一样,不能对其进行整体赋值,只能给各个元素赋值,而字符指针变量可以直接用字符串常量赋值。例如,若有如下定义:,char a[10];,,char *p;,则语句,a=,”computer”,;,是非法的,因为数组名,a,是一个常量指针,不能对其赋值。只能对各个元素分别赋值:,a[0]=’c’;a[1]=’o’;a[2]=’m’;a[3]=’p’;……;a[7]=’r’;,但语句:,p=,”computer”;,,是合法的。,10/3/2024,82,,C,语言程序设计教程,8.5.2 指针数组与命令行参数,,

65、在操作系统命令状态下,可以输入程序或命令使其运行,称,命令行状态,。输入的命令(或运行程序)及该命令(或程序)所需的参数称为,命令行参数,。,,如:,copy,fd fs,,,copy,是文件拷贝命令,,fd,、,fs,是命令行参数。,,main,函数是可以有参数的,但与普通函数不同。,,带形参的,main( ),函数的一般形式是:,,main,(,int argc,, char *,argv,[ ]),,{ … },,形参,argc,记录命令行中字符串的个数,,argv,是一个字符型指针数组,每一个元素顺序指向命令行中的一个字符串。,10/3/2024,83,,C,语言程序设计教程

66、,1.,main(),函数的形参与实参,,,main(),函数由系统自动调用,而不是被程序内部的其它函数调用,,main(),函数所需的实参不可能由程序内部得到,而是由系统传送。,,,main(),函数所需的实参与形参的传递方式也与一般函数的参数传递不同,实参是在命令行与程序名一同输入,程序名和各实际参数之间都用空格分隔。,,,格式为:执行程序名 参数1 参数2 …… 参数,n,,形参,argc,为命令行中参数的个数,(包括执行程序名),其值大于或等于1,而不是象普通,C,语言函数一样接受第一个实参。,,形参,argv,是一个指针数组,其元素依次指向命令行中以空格分开的各字符串。,,,即:第一个指针,argv,[0],指向的是程序名字符串,,argv,[1],指向参数1,,argv,[2],指向参数2,……,,argv,[n],指向参数,n。,10/3/2024,84,,C,语言程序设计教程,2.命令行参数的传递示例,例,8.11,分析下列程序,指出其执行结果,该程序命名为,exam.c,,经编译连接后生成的可执行程序为,exam.exe,#,include <,stdio,.

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

相关资源

更多
正为您匹配相似的精品文档

相关搜索

关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!