




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、 分析C程序的变量所存放的数据: 数值型数据:整数、实数这些变量具有以下性质: 占有一定长度的内存 单元 如:int x; x占二字节、二个单元 每一个变量都有一个地址,为无符号整数,称为地址,它不同于一般的整数。问题:能否对地址运算?能否用一个变量保存地址? 字符型数据:字符、字符串10.1 指针的概念指针的概念一、数据在内存中的存放一、数据在内存中的存放系统分配i在地址为2000的单元内存:为一个连续编号(连续地址)且以一个单元为一个字节的连续存贮区。 若程序中定义了三个int变量i, j, k int i= 5, j=5, k=10; 20002001200220032004200530
2、01 5+5102000j在地址为2002的单元k在地址为2004的单元当程序中要用它们的值时: y=i+j+k;则系统通过一张变量名与地址对应关系表:分别 找到i的地址为2000,将2000,2001中的数据5读出;找到j的地址为2002,将2002,20003中的数据5读出;找到k的地址为2004,将2004,2005中的数据10读出。直接访问:在程序中表现为直接使用存放该数据的变量名。 间接访问:如果将某一变量的地址(如i的地址2000)存放到另一个变量x,则可通过x来存取i的值。上述过程称为变量的“ 直接访问” 52000i直接访问53001i间接访问2000 x 显然,x与i是通过i
3、的地址联系起来的,一个变量的地址称为该变量的指针。因此,i的指针为2000,而存放地址(指针)的变量叫做指针变量。 如:x5510.2 指针变量的定义和引用指针变量的定义和引用 首先明确一个概念:指针变量也有类型,因为类型涉及到所占单元数,也就是指针变量在计算时有所不同。例如: 当x为一个指向float型的指针变量时 x1:设x为2000,则x+12004 当x为一个指向整型变量的指针变量时。 x+1: 设x原为2000,则x+12002一、一、 定义指针变量的形式:定义指针变量的形式:表示该变量为指向某类型变量的指针变量x只能指向整型变量,即只能存放整型变量的地址。如: int x;类型名
4、变量名二、引用指针变量二、引用指针变量 将一个变量的地址(指针)赋给一个指针变量,用取地址运算符:&int i, j, x; x=&i; 如果将整数赋给地址量x=1000;编译会提出警告性错误,但还是有值(地址) 存取指针变量所指向变量(目标变量)的值: 用指针运算符*, 即:*x 为 i , &为同级运算符,结合性自右至左。则当&或&在一起时,具有抵消作用如上例: &i相当于xi &x相当于&ix三、指针变量作为函数参数三、指针变量作为函数参数但当用地址(指针变量)作参数时,与数组名类似。 则:形参、实参均为地址量。形参,于是,
5、形参数前面讲过:函数实参传递单向据值的改变不会影响实参。例: swap(p1, p2) int p1, p2; int p; p=p1; p1=p2 p2= p; main( ) int a, b; int x1, x2; scanf(%d,%d,&a, &b); x1=&a; x2=&b; swap(x1, x2); printf(%d,%d n,a, b);执行过程分析(设a10, b20) &a&b2010 x1ax2b&a&a&b&b1020p1p2x1x2abp= p1; p1= p2; p2 =p;10
6、20abp1p2p&a&a&b&b2010p1p2x1x2ab 释放p1, p2后&a&b1020 x1ax2b1. 注意函数中p为普通变量,并非地址量,如p为地址量,它为哪一个变量的地址?这时: int t,*p=&t;(允许) p= p12. 如果swap函数中的交换语句改为: int p1, p2, p; p=p1; p1=p2; p2=p; 则仅将p1, p2的指向改变,函数返回后,p1, p2释放, a、b中的内容依然未改变。 sway(p1, p2)int p1, p2; int p;p=p1;p1=p2;p2=p; 则:只将
7、p1,p2的内容改变,而不能使a, b交换。3. 不用地址量,也未能实现交换,即:4. 结论:当需要被调函数改变调用函数中n个变量的值时,需将这n个变量的地址(用指针变量、或直接用地址量&a, &b)作为实参传给指针形参,且被调函数通过改变指针形参所指向的变量来实现实参中变量值 的改变。10.3 数组的指针及指向数组的指针变量数组的指针及指向数组的指针变量前面介绍:一个变量的地址为该变量的指针。当用一个变量来存放该地址(指针)时,称为指针变量。又有说明: 一个数组元素相当于一个简单变量。于是,亦可用一个指针变量来指向数组元素。不同点: 数组元素连续地占用内存单元,则当一个元素的
8、指针已知时,其它元素的指针亦可知道。 定义方法与简单变量指针定义相同,但引用略有不同例: int a10; int p; 定义p=&a0; 将a的第0个元素的地址p C语言规定: a的首地址即可用&a0表示,亦可用a表示 所以:p=&a0; 和 p=a等价一、数组元素指针变量的定义与引用一、数组元素指针变量的定义与引用可以在定义指针变量时赋初值: int p=&a0; 或 int p=a; (等价于) int p; p=a;它不同于语句: p=&a0;1. 由首地址指针来引用数组中的其它元素。 设p为a的首地址,p=a,或p=&a0; p+1为a
9、1的地址,当a为int,p+1相当于地址+2, 而当a为float时,p+1相当于地址+4.则p+1是什么意思?一般地: p+i ai 的地址,或为a+i引用ai的值: ai, (p+i), (a+i)例:int a10, i; int p; p=a;则: (a+i)和ai都得计算元素地址,而p+后,p可直接指向ai。2. 在搜索数组元素时,用p+i比ai+来得快3. 关于指针的运算 指针运算符 与+, 同级,且自右至左。 p+ / p 的作用: 若p=a或p=&a0, 则p+相当于p=p+1, 即指向a1 若p=&a5, 则p 相当于p=p 1,即指向a4 (p)+ 或(p)
10、 (p)+:将p指向的变量的值自增1; (p) : 将p指向的变量的值自减1。 p+与(+p) p+相当于(p+) 若p=&a0, 则:先取p的值,即 a0的值,再使p+1, p指向a1. (+p)为先使pp+1, p指向a1, (+p)取出a1的值。 前面已叙述过,当实、形参均为数组名时,调用时将实参数组首地址传递(单向)给形参数组,使它们共享内存。 例:编写函数,将数组各元素值取反。 main ( ) void invert( ); int a10, i; for (i=0;i10; i+) scanf( %d, &ai); invert(a, 10);二、数组名作函数参数
11、二、数组名作函数参数 for (i=0; i10; i+) printf(a%d=%d, ,i, ai); void invert(x, n) int x , n; int i; for (i=0; in; i+) xi= xi; return; 分析参数传递情况:a10:a0 a1 a2 a9axx0 x1 x9即:x, a共享同一段内存单元。前面已分析: 可用指针表示数组。即:指针运算引用数组元素,于是,可用指针变量作为形参接收实参数组首地址。函数改为: void invert (x, n) int x, n; int i; for (i=x; i(x+n) ;i+) i= i retur
12、n;参数传递情况:a0 a1 a2 a9a:xx+1x+9 x (x+1)(x+9) 进一步分析:在主函数中也不一定要用数组名a,只要用一指针变量即可。设int p; p=&a0, 则: invert(p, n); 即可完成同样功能总结以上情况,有四种参数传递形式: 特别是(3)种情况:当不是数组元素时,即实参形参均为单个指针变量时,实现了实、形参共用内存单元。(1) 实参、形参均为数组名(2) 实参为数组名、形参为指针变量(3) 实参、形参均为指针变量(4) 实参为指针变量,形参为数组名。1. 多维数组的地址: 将一维数组内容扩充,也可用一指针变量指向多维数组,以二维数组为例加以讨论
13、。设: static int a34 = 1, 2, 3, 4, 5, 6,7, 8, 9, 10, 11, 12;三、指向多维数组的指针和指针变量。三、指向多维数组的指针和指针变量。1212345678910 11第1行第2行第3行a0a0+1a0+2a0+3a1a1+1a1+2a1+3a2a2+1a2+2a2+3数组名a0 数组名a1数组名a2aa+1a+1 设首地址a:2000, 则a+1:2008, a+2: 2016 从一维数组中我们认为:a0与a, (a+0)等价所以:a0i的地址&a0i还可表示为(a+i)于是:aij可表示为 *(*(a+i)+j) a0i的地址:a0+
14、i, a+i, 和&a0i a1i的地址:a1+i, (a+1)+i, &a1i aij的地址:ai+j= (a+i)+j 有了多维数组的地址概念后,可用指针变量来指向多维数组 设二维数组的大小为m*n, 则第i, j个元素相对于a00的个数为mi + j (i=0,1,,n1)2. 多维数组的指针 指向数组元素 当用一个指针变量指向第0行的首地址后,即可搜索到全部元素。设:int p; p=a0; 则第aIj 的地址为p+i m+jmain ( ) static int a34=1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12; int p; for
15、 (p=a0; pa0+12; p+) if (p a0) %4= =0) printf(n); printf (%4d, p); 例: 设有一34的二维数组,利用指针逐行逐个输出元素。注: 为什么p的初值不能写成p=a;?仍为上例为例: 当p=a, 则p+1为下一行首地址,于是引用第(i, j)个元素的方法:第i行首地址,相当于ai 这时,需将p的定义改为 int (p)4; 指向数组的每一行(p+i)+j) a) 不能去掉( ),否则为int p4为指针数组 b) 之所以这样定义是为了使p+1的地址为a1, 即:移动4个元素。例:有一个班,3个学生,各学4门课,计算总平均分数,以及第n个学
16、生的成绩。程序如下: main ( ) void average( );void search ( );static float score 3 4=65, 67, 70, 60,80,87,90,81, 90,99,100,98;average (*score, 12); /*求12个分数的平均分8*/search( score,2); /*求第2个学生成绩*/void average (p, n)float *p; int n;float *p_end;float sum=0, aver;p_end=p+n1;for (; p=p_end; p+) sum=sum+(*p);aver=su
17、m/n;printf(average=%5.2fn, aver);void search (p, n)float (*p) 4; int n;int i;printf(the scores of No.%d are:n, n);for (i=0; i4; i+) printf(%5.2f , *(*(p+n)+i);程序运行结果如下:average=82.25the scores of No. 2 are:90.00 99.00 100.00 98.00 设有三个学生,各有四门功课,求总的平均分,各学生总分,且将三个学生的成绩按总分排序。要求用指针变量:应有举例: 实参可用指向一维数组的指针变
18、量;即: 数组名 实参可用指向数组的指针变量(实数组名) 输入三学生单科成绩一、流程图:计算各学生总分计算总平均分按各学生总分排序打印各科成绩总分及总平均分结束调用函数sumscore(p,n)指针,指向一维数组调用函数average(p,n)调用函数sort(p,n)调用函数printscore(p,n)学生人数指向二维数组 人数返回值float指向一维数组人数指向二维数组人数main ( ) void sumscore ( ); float average( ); void sort( ); void printscore( ); static float score35=65, 80,
19、90, 100, 80, 66, 75, 90, 58, 60, 90, 83;二、程序1. 主函数sumscore(score, 3);printf(n average=%f, average(score, 3);sort(score, 3);printscore(score, 3); void sumscore(p, n)float p; int n; float aver, p_end;p_end=p+5 n 1;for (; p=p_end; p=p+5) (p+4)= p+ p(p+1)+ (p+2)+ (p+3); 2. sumscore函数求总分float average(p,
20、n)float (p)5;int n; float aver=0.0; int i; for (i=0; in; i+) aver=aver+ (p+i)+4); aver=aver/nreturn(aver); 3. average函数求总平均分有二种方法:(1)循环时用简单变量 (2)循环时用指针变量方法(1)void sort (p, n)float p;int n; int i, j, k, m; float t;for (i=0; in 1; i+)3. sort函数排序 k=i; for (j=i+1; jn; j+) if (p+4+5 i) (p+4+5 j) k=j; if
21、(k!=i) for (m=0; m5; m+) t= (p+m+5 i); (p+m+5 i)= (p+m+5 k); (p+m+5 k)=t; 方法(2)void sort (p, n)float pint n; float p1, p_end, k, t;int m;p_end=p+5 n 1;p=p+4;for (; pp_end 5; p+=5) k=p; for (p1=p+5; p1p_end; p1+=5) if (p p1) k=p1; if (k!=p) for (m=0; m5; m+) t= (p m); (p m)= (k1 m); (k1 m)=t; void pr
22、intscore(p, n)float (p)5;int n; int i, j;printf(n A B C D sumn);for (i=0; i0; i+) printf(n);for (j=0; jy)? x:y; return(z); main ( ) int max( ); int (p)( ); int a, b, c; p=max; scanf(a=%d, b=%d, &a,&b); c=(p) (a, b) printf(max value=%d, c)4. 对函数指针变量进行运算无意义。二、函数指针变量作为函数参数二、函数指针变量作为函数参数 意义:当一个函
23、数被调用后,执行过程中需根据实际情况调用f1, f2,或调用f3, f4,于是在该函数中即可用函数指针变量作形式参数。前面介绍过:简单变量、数组名、指针变量均可作为函数的参数。能否用函数指针变量作参数呢?当然可以!例:sub (x1, x2) int (x1 )( ), (x2 )( ); int a, b, i, j; a=(x1) (i); b=(x2) (i, j) 于是,可用 sub(f1, f2)或sub(f3, f4)调用sub,表示执行sub时,根据实参传递过来的函数入口地址而调用f1, f2或f2, f4.例2. 设计一个函数process, 每次实现不同的功能,当用不同的函数
24、名作实参调用process时,process再去调用相应的函数。程序如下:main ( )int max( ), min( ), add( );int a, b;printf(enter a and b:);scanf(%d, %d, &a, &b);printf(max=);process(a, b, max);printf(min=)process(a, b, min);printf(sum=);process(a, b, add);max(x, y)int x, y;int z;if (xy) z=x;else z=y; return(z);min(x, y)int x,
25、 y;int z;if (xy) z=x;else z=y; return(z);add(x, y)int x, y;int z;z=x+y;return(z); process (x, y, fun) int x, y; int (* fun) ( ); int result; result=(*fun) (x,y); printf(%dn, result); 注:当用函数名作参数时,不论函数返值类型如何均应作说明,以与变量名相区别。运行情况如下:enter a and b:2, 6max=6min=2sum=8 本概念比较简单,既然函数返回值可以是整、实型等数据。当然也可以是指针值,只是函
26、数定义形式略有不同:例: 有若干个学生的成绩(每个学生有4门课程),要求在用户输入学生序号以后,能输出该学生的全部成绩。用指针函数来实现。类型标识符 函数名(形参表列)float * search ( );float * p;int i, m;printf(enter the number of student:);scanf(%d, &m);printf(The scores of No. %d are :n, m);程序如下:static float score 4=60,70,80,90, 56,89,67, 88, 34, 78, 90, 66;main ( )p=search
27、 (score, m);for (i=0; i4; i+) printf(%5.2ft, * (p+i); float * seaarch (pointer, n)float (* pointer) 4;int n;float * pt;pt= * (pointer +n);return (pt);运行情况如下:enter the number of student: 1The scpres pf Mp. 1 are:56.00 89.00 67.00 88.00一、指针数组一、指针数组1. 定义形式 类型说明符 数组名常量数组同种类型的数据集合。 当每一个元素均为指针类型数据时,该数组被称为
28、指针数组。例:int p10; p为指针型数组,其每一个元素为一指针型变量。用来存入一组地址。一个重要的应用存放一组字符串 在对字符串排序时,若交换数组元素,时间太长。 所以,用指针数组(一维)保存各字符串首地址,且交换时只需交换指针数组各元素首地址即可解决上述二个问题。 字符串长度不一,于是只得以最长字符串的长度作为二维数组列数,造成空间浪费。 一般情况下,当有一组字符串,如一组书名,也可用二维字符数组存放,但存在二个问题:2. 应用例:将若干字符串按字母顺序(由小到大)输出。main ( )void sort ( ); void print ( ); static char * name =Follow me, BASIC, Great Wall, FORTRAN, Computer design;int n=5;sort (name, n);print(name, n);void s
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 装修房子工人合同协议
- 补充协议延长劳动合同
- 装修工人赔付协议书模板
- 视频编辑承包合同协议
- 蛋糕店加盟协议合同协议
- 蒙古国煤矿购销合同协议
- 舞台灯泡采购合同协议
- 苗木采购定金合同协议
- 船厂设备转让合同协议
- 菜市场店铺买卖合同协议
- 2025届鄂东南省级示范高中联盟高考英语二模试卷含答案
- 2025购销合同范本下载
- 2024年家政服务职业技能大赛家庭照护赛项决赛试理论题库1000题
- 2025年四川省成都市成华区中考二诊英语试题(含笔试答案无听力音频及原文)
- 2025劳动合同范本下载打印
- 管道试压吹扫方案
- Unit 4 Clothes 单元整体(教学设计)-2024-2025学年人教精通版(2024)英语三年级下册
- 大概念视角下的初中数学函数单元整体教学设计研究与实践
- 《建筑装饰设计收费标准》(2024年版)
- 肾上腺皮质功能减退症的护理
- 2025届高考语文专项【语用新增题型】修改错别字名校最模拟题
评论
0/150
提交评论