中央电大C语言A课程辅导(5)_第1页
中央电大C语言A课程辅导(5)_第2页
中央电大C语言A课程辅导(5)_第3页
中央电大C语言A课程辅导(5)_第4页
中央电大C语言A课程辅导(5)_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、C语言程序设计A课程辅导(5)-第5章 指针主要内容: 一、指针的概念 二、指针变量 三、指针运算 四、指针与数组 五、动态存储分配 六、使用指针和动态存储分配的程序举例一、指针的概念l 指针:计算机内部存储器中一个存储(单元)字节的地址。该地址是一个32位的二进制编码,所占有的字节数(指针类型长度)与int类型长度相同。指针是一种特殊的数据,即不是字符和常数,而是内存单元的编码(地址)。l 指针与数据类型:在C语言中每个指针都与一个具体的数据类型相联系,即为内存中存储该类型的一个数据的地址,具体为数据所占用存储空间(又称为存储单元或数据单元)的首字节地址。如int x=10; 则x的地址就是

2、一个指针,它是存储x的值10的4个存储字节的第一个字节的地址。l 指针类型:就是它所指向的存储单元中所存数据的类型。如一个指针指向一个整型数(即所指向的存储单元中存储的是整数),则称为整型指针;若指向一个字符,则成为字符指针。l 数据地址的表示:在一个变量前加上&字符,就表示取该变量的地址,该地址(指针)的类型就是该数据的类型。如int x; &x就表示x的地址,其类型为int指针类型,可表示为int*。l 空指针:其值为0的指针称为空指针。空指针不指向任何数据,在stdio.h头文件中已经把NULL定义为0,所以符号常量NULL也表示为空指针。二、指针变量 能够保存存储单元地址的变量。一般变

3、量保存的是字符或常数。l 定义格式: * =,.; 与一般变量定义语句格式基本相同,只要在变量标识符前加上*即为指针变量。l 格式举例:(1) int x, *p; /定义x为int型一般变量,p为int*型指针变量(2) int a=10, *pa=&a; /定义int变量a并初始化10,同时定义pa为 /int*类型的指针变量,并初始化为a的地址,即整数变量的地址(3) char *p1=0, *p2=pointer; /p1为空,p2指向字符串pointer /把pointer的第1个字符的地址赋给指针变量p2,类型为char*(4) char *d5=0; /字符数组d5中每个元素均为

4、指针变量,其值为空(5) int x=5, *px=&x, *pp=&px; /px: int*类型,pp: int*类型 pp px x &px &x 5 /px的地址具有int*类型(6) char * rp3=front,middle,rear; /定义指针数组和初始化(7) int a10, *ps=a; /数组名a的值是第1个元素的地址, /即a0元素的地址&a0,类型为int*l 输出一般指针和输出字符指针所指向的字符串:输出一般指针时使用的格式符为%p,输出字符指针所指向的字符串时使用的格式符为%s。例如: #include void main() int a=30; char

5、*cp; /能够保存一个字符变量或数组元素的地址 cp=output; /cp指向字符串常量output printf(%p %pn,&a,cp); /输出指针,分别为a和o的地址 printf(%d %sn,a,cp); /输出a的值和cp所指向的字符串 运行结果: 0013FF7C 0042002C /十六进制8位 30 outputl 向字符指针输入字符串: char a30; scanf(%s,a); /gets(a); char a30, *p=a; scanf(%s,p); /gets(p);l 利用typedef语句定义指针数据类型: (1) typedef int* inPoi

6、nter; / 定义inPointer为int*类型, /若用inPointer s1=NULL; 等价于int* s1=NULL; (2) typedef char* chPointer; / 定义chPointer为char*类型 (3) typedef char *AA10; / 定义AA为char*10指针数组类型, /若用AA aa; 等价于char* aa10;三、指针运算包括赋值、取地址、间接访问、增减1等。l 赋值(=)双目运算,把赋值号右边的指针(地址)值赋给左边的同类型的指针变量。int x=30, *px, *py;px=&x; py=px; /把x的地址赋给px,把px

7、值赋给py,它们均指向xl 取地址(&)单目运算,使用在一般变量的前面,表示取变量的地址。char ch= +, *p=&ch; /取ch变量的地址赋给p,p指向chchar s30=Apple, *ps=s; /字符数组s的地址赋给ps,ps指向s, /s和ps的值均为s数组中第1个元素A的存储地址l 间接访问(*)在指针前面使用*运算符能够访问到指针所指向的对象。如:int x=12, *px=&x; /px指向x,px所指向的对象x的值为12printf(%dn,*px+10); /22,使用*px+10等同于x+10*px+=15; /27,使用*px+=15等同于x+=15,*px即

8、x的值变为27l 增1(+)和减1(-)单目运算,可使用在指针变量的前面或后面,使指针变量的值增1或减1。int a5=10,15,20,25,30, x,y;int *p=a; /p指向a0元素,即p的值为a0的地址x=*p+; /x的值为10,p加1后赋给p,p指向下一个元素a1x=*+p; /x的值为20,p指向元素a2y=(*p)+; /y的值为20,a2被加1后赋给a2,a2的值变21p-; /运算前p指向a2,运算后p指向a1printf(%dn, *p-); /输出a1的值15,然后p减1后指向a0p=&a3; printf(%dn,-*p); /*p的值25,输出减1后的a3的

9、值24注意:当指针变量p指向数组中的一个元素时,p+或+p则使p指向其下一个元素,p或p则使p指向其前一个元素。若p指向ai,则进行p+或+p运算后,p指向ai+1;若p指向ai,则进行p-或-p运算后,p指向ai-1。l 加(+)和减(-)双目运算,使指针向后或向前移动若干个数据位置。int b6=1, 3, 5, 7, 9, 11;int *p=b, *q=p+5; /p指向b0,q指向b5,p+5等同于b+5printf(%dn, *(q-3); /输出b2的值5p=b+6; /p指向b6数组后面的一个数据单元,即b5后的位置*-p; /取b5元素的值11 l 加赋值(+=)和减赋值(-

10、=)双目运算,左边的指针变量加上或减去右边相应的值。char a20=wbcdefghi; char *p=a; /p指向a0,即字符wp+=7; /运算后p指向a7,即字符hp-=4; /运算后p指向a3,即字符d*p-=3; /运算后使a3的值减3,由100(d的ASCII码)变为97(a的码)l 比较(=,!=,=)双目运算,比较左右两个指针(地址)的大小。数组中后面元素的指针大于前面元素的指针,即&ai+1&ai。int a5=20,15,32,48,46;int *p;for(p=a; p=a; p-) printf(%d , *p); /逆序输出a中每个元素值这一讲就到这里,同学们

11、再见!四、指针与数组 1. 指针与一维数组l 一维数组名是指向该数组第一个元素的指针常量12251830634450 int a7=12,25,18,30,63,44,50; 0 1 2 3 4 5 6 a *a表示a0元素,*a的值即为a0的值。 a的值等于&a0,类型int*。 a为指针常量,即其值不可修改,所以使用a+是错误的。道理很简单,如果允许修改数组名的值,以后就无法访问该数组了。l 数组元素的下标和指针访问方式ai等价于*(a+i),分别为下标和指针访问方式。*a与a0,*(a+1)与a1等价。假定int *p=a+i; 则 *p与ai,*p+与ai+等价。for(i=0; i7

12、; i+) printf(%5dn,ai); /下标方式 等价于:for(i=0; i7; i+) printf(%5dn,*(a+i); /指针方式等价于:for(p=a; pa+7; p+) printf(%5dn,*p); /指针方式等价于:for(p=a,i=0; i7; i+) printf(%5dn,pi);/下标方式 /p初始指向数组a中第1个元素,pi与ai等价,均为*(a+i) 2. 指针与二维数组l 二维数组名是指向该数组第一行元素的指针常量,其值为整个二维数组空间的首地址int b34=1,2,3,4,2,4,6,8,3,6,9,12;b为指向b0行4个元素的指针常量,其

13、值为&b0,亦即&b00的值,但类型为int(*)4,而不是int*。bi为i行元素(一维数组)的数组名,bi的值为bi0元素的地址。它们的类型均为int*。而&bi的值虽然也等于bi0元素的地址,但类型为int(*)4,因为它是该行元素的首地址。同一维数组名一样,不允许修改二维数组名的值,如进行b+操作是错误的。l 二维数组名的值可以赋给同类型的指针变量int (*pb)4=b; /把b的值赋给同类型的指针变量pb,pb也指向此数组, /此后pb也可以作为数组名使用,访问任何元素pb23等价与b23,值为12。注意:int (*pb)4与int (*pb)5不同,因为pb所指向的元素个数不同

14、。若int *pb4的则定义pb为含有4个元素的整型指针数组,而不是定义指向含有4个整型元素的数组的指针。l 二维数组元素的下标和指针访问方式bij (*(b+i)j 或 *(bi+j) 或 *(*(b+i)+j) /均等价 for(i=0; i3; i+) for(j=0; j4; j+) printf(%d , bij); / *(*(b+i)+j) printf(n); l 使用指针和数组的程序举例例1:#include void main() int a8=3,5,7,9,11,13,15,17; int i,*p=a; /p的值为&a0 for(i=0;i8;i+) printf(%

15、5d ,*p+); /先*p,后p的值加1 if(i+1)%4=0) printf(n); /输出4个元素后换行 输出结果: 3 5 7 9 11 13 15 17例2:#include void main() int a8=46,38,72,55,24,63,50,37; int max=*a, min=*a; /a0的值赋给max和min int *p; for(p=a+1; pmax) max=*p; /大放max if(*pmin) min=*p; /小放min printf(%5d %5dn, max,min); /输出最大和最小值 输出结果: 72 24五、动态存储分配 1. 动态

16、存储分配的概念 变量和数组在计算机内存中都有对应的存储空间,该存储空间的分配时机有两种:一种在编译阶段,或者说在程序运行前;另一种在程序运行之中。前者称为静态存储分配方式,后者称为动态存储分配方式。l 变量的静态存储分配方式通过一般的变量定义语句定义的变量,采用的是静态存储分配方式。如:int x,y; /x和y分别对应的4个字节的存储空间是静态分配的int a10; /数组a所需要的40个字节的存储空间是静态分配的char b20,*p=b; /数组b的20个字节和指针变量p的4字节是静态分配的double cMN=0; /数组c的M*N*8个字节的存储空间是静态分配的l 变量的动态存储分配

17、方式变量的动态存储分配需要调用在系统头文件stdlib.h中声明的动态存储分配函数来实现,这些函数为malloc()、calloc()和realloc()三种。 2. 动态存储分配函数的原型格式和功能l malloc()函数原型格式 void* malloc(unsigned int k); 功能:调用它时能够分配k个字节的存储空间,并把第1个字节的地址返回,该返回值具有void*类型,可以赋给任一具体类型的指针变量。l calloc()函数原型格式 void* calloc(unsigned int n, unsigned int k); 功能:调用它时能够分配n*k个字节的存储空间,并把第

18、1个字节的地址返回,该返回值具有void*类型,可以赋给任一具体类型的指针变量。通常用n表示数组长度,k表示元素类型的长度。l realloc()函数原型格式 void* realloc(void* ptr, unsigned int k); 功能:调用它时能够分配k个字节的存储空间,接着把ptr已经指向的动态分配的存储空间的内容复制到新分配的存储空间中,最后把新分配的存储空间的第1个字节的地址返回。由于该返回值具有void*类型,所以能够赋给任一具体类型的指针变量,通常仍赋给ptr所对应的实参指针变量,使得通过该调用后增加或缩小动态存储空间。 3. 动态存储分配的调用格式举例 (1) int

19、 *pn=malloc(sizeof(int); /分配一个整数存储空间由指针变量pn所指向,此动态分配的变量 /为*px,可用它保存一个整数,如:*px=25; *px+=30; /其值为55 (2) double *pa=calloc(10,sizeof(double); /分配一个具有10个双精度元素的一维数组空间,由指针变量pa /所指向,pa也就是该动态数组的数组名(但有区别,它是变不是常), /通过它可以访问该数组中的任何元素。如:*pa=12; 把12赋给 / pa0元素;又如:paipaj进行两元素大小的比较 (3) pa=realloc(pa,20*sizeof(double

20、); /增加pa指针所指向的存储空间的大小,由10个双精度元素变为 /20个双精度元素,同时原有的存储内容被复制过来。 (4) int *top=calloc(M+1,sizeof(int*); /top动态数组含有M+1个元素,每个元素能够存储一个整数的地址。 4. 动态存储分配的优点允许在程序运行过程中随时确定待使用的存储空间的大小,不必象静态分配那样需要事先确定。一般定义一个数组时,必须确切给出数组的每一维的尺寸,如:int a10, bMN; /M和N必须是已经定义的符号常量动态分配定义一个数组时,所分配的存储空间的大小可以是常量,也可以是变量。如:(1) int a=calloc(1

21、0,4); /两个参数都为常量(2) int a=calloc(x,4); /第1个参数为变量,分配x个整数元素的空间(3) char b=malloc(n1+n2); /n1和n2为变量,分配n1+n2个字节的空间(4) char c=malloc(sizeof(d); /根据另一个对象d的大小分配空间 5. 动态存储空间的释放 释放动态存储空间的free()函数的原型格式 void free(void* ptr); 功能:调用它时能够把指针变量ptr所指向的动态存储空间释放掉,即归还给操作系统。 free()函数原型声明也包含在stdlib.h系统头文件中 当动态存储空间保存的内容不再使用

22、时,可调用该free()函数及时释放掉,若没有调用它,则一直到程序运行结束时该动态存储空间才被自动释放给操作系统。 对于一般静态分配的变量,其占有的存储空间只能由C语言系统在运行时自动释放,其时机为所在的模块(复合语句)刚执行完毕。 下面看一个程序例子 #include /支持调用标准输入和输出操作的函数 #include /支持调用动态存储分配和释放函数 void main() int *a=calloc(10,sizeof(int); /动态分配得到a10数组, /为40字节的存储空间,同时静态分配得到a指针变量,4字节 int i; /静态分配得到i整数变量,4字节 for(i=0; i

23、10; i+) ai=i*i; /给a数组中每个元素赋值 for(i=0; i10; i+) printf(%d ,ai); /输出a中每个元素值 printf(n); /输出一个换行符 free(a); /a10数组的40个字节的动态存储空间被交还给操作系统 /此主函数执行结束时,自动把a和i各占有的4字节交还给操作系统 程序运行结果: 0 1 4 9 16 25 36 49 64 81六、使用指针和动态存储分配的程序举例例1:以指针方式访问数组元素的例子 #include #include void main() int a5=3,6,9,12,15; int *p=a; /把数组a的首地

24、址赋给指针变量p int i; for(i=0;i=a; p-) printf(%5d,*p);/从后向前访问数组元素 printf(n); /换行 输出结果: 3 6 9 12 15 15 12 9 6 3例2:进行简单变量动态存储分配的例子 #include #include void main() int x=23,y=40,z; int *p1=malloc(sizeof(int); /为*p1动态分配4字节存储空间 int *p2=malloc(sizeof(int); /为*p2动态分配4字节存储空间 *p1=x; *p2=y; /分别把x值23和y值40赋给动态变量*p1和*p2

25、 printf(%d %dn,*p1,*p2); /输出*p1和*p2的值为23 40 z=*p1; *p1=*p2; *p2=z; /交换*p1和*p2所保存的值 printf(%d %dn,*p1,*p2); /输出*p1和*p2的值为40 23 free(p1); free(p2); /释放p1和p2各自所指向的动态存储空间 程序运行结果: 23 40 40 23例3:动态存储分配任意大小的一维数组的例子 #include #include void main() int n,i,sum=0; int *a; printf(从键盘给n输入一个正整数(1-10): ); while(1) scanf(%d,&n); /输入1-10之间的数到n中 if(n=1 & n=10) break; else printf(重输: ); a=calloc(n,sizeof(int); /动态分配an数组空间,n是变量 a0=0; a1=1; /给a数组的前2个元素赋值 for(i=2; in; i+) ai=a

温馨提示

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

评论

0/150

提交评论