《C语言程序设计与实验指导》-8_第1页
《C语言程序设计与实验指导》-8_第2页
《C语言程序设计与实验指导》-8_第3页
《C语言程序设计与实验指导》-8_第4页
《C语言程序设计与实验指导》-8_第5页
已阅读5页,还剩28页未读 继续免费阅读

下载本文档

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

文档简介

本章目录8.1指针和指针变量的概念8.2用指针访问变量8.3数组与指针8.4字符串与指针8.5指针作函数参数8.6返回指针值的函数8.7指针数组和指向指针的指针8.8函数的进一步讨论8.1指针和指针变量的概念C程序中定义变量,在对程序编译时,就为变量分配内存单元。内存的每一个单元都是有地址的。一个变量可以被分配多个内存单元,一般认为第一个内存单元的地址就是该变量的地址。在程序中,变量和变量的地址是一一对应的。当程序想访问变量时,先确定该变量的地址,然后在内存中寻找该地址,再读取该地址内存单元中的内容。因此,C语言中访问变量,是通过访问变量的地址来完成的。例如有定义变量的语句:inti;

程序先在内存中为变量i分配4个字节2000,2001,2002,2003。一般认为变量i的地址是2000。有输出语句:printf(“%d”,i);

根据变量i的地址是2000,在内存中寻找地址为2000,连续4个的内存单元,读取数据,再输出。这种按变量地址存取变量值的方式称为“直接访问”方式。8.1指针和指针变量的概念

还有另外一种访问方式,称之为“间接访问”方式,将变量i的地址存放在另一个变量中。假设定义变量p用来存放变量i的地址,则变量p指向i。若需访问i,则首先应访问变量p,以获得i的地址。变量的地址称为该变量的指针。例如变量i的指针是2000。用来存放指针的变量称为指针变量。例如变量p就是指针变量。

8.2用指针访问变量

8.2.1指针变量的定义、赋值

指针变量的定义形式:类型名*指针变量名;

例如:int*p;

其中,星号*是一个类型说明符,说明变量p是一个指针变量,即用来存放地址的变量。类型名是指针变量p所指向的变量的类型。也可同时定义多个指针变量。例如:

int*p1,*p2;inti=3,j=4;p1=&i;p2=&j;

指针变量中只能存放地址,不能将一个整数赋给一个指针变量。p=1000;这种赋值是不合法的。8.2.2指针变量的引用对于指针变量,有两个有关的运算符:(1)&:取地址运算符。分析下列程序语句是否合法:inti=10,k;int*p1=&i;/*合法,p1指向变量i*/int*p2,*p3;float*p;p2=&i;/*合法,p2指向变量i*/p3=p1;/*合法,p2的值为&i,即p2指向i*/k=p3;/*不合法,k是一个普通的整型变量,不能将一地址赋给k*/p=&i;/*不合法,p是一个指向float型变量的指针变量,而i是整型变量*/8.2.2指针变量的引用(2)*:指针运算符,取其指向的内容。分析下列程序语句是否合法:inti=10,j=20;intk,m,n,l;int*p1=&i;/*合法。指针变量p1指向i*/int*p2;int*p3;p2=&j;/*合法。指针变量p2指向j*/k=*p1;/*合法。将*p1的值10赋给k*/m=*p2;/*合法。将*p2的值20赋给m*/n=*p3;/*不合法。p3未定义,因此*p3无值*/*p3=i;/*不合法。p3未定义,因此*p3无值*/n=p3;/*不合法。n是整型变量,不能存放地址*/l=*p1**p2;/*合法。即l=10*20*/8.2.2指针变量的引用例8.1执行以下程序后,a的值为(),b的值为().#include<stdio.h>voidmain(){inta,b,k=4,m=6,*p1=&k,*p2=&m;a=p1==&m;b=(-*p1)/(*p2)+7;printf("a=%d\n",a);printf("b=%d\n",b);}8.2.2指针变量的引用例8.2若输入值为3和5,分析以下程序执行过程中变量值的变化。#include<stdio.h>voidmain(){int*p_max,*p_min,*p,a,b;scanf("%d,%d",&a,&b);p_max=&a;p_min=&b;if(a<b){p=p_max;p_max=p_min;p_min=p;}printf("\na=%d,b=%d\n",a,b);printf("max=%d,min=%d\n",*p_max,*p_min);}8.3数组与指针

8.3.1一维数组与指针

例如有:inta[10],*p;p=a;a是数组名,即数组首元素的地址。将a赋给p,则p的值就为数组首元素的地址,p指向a[0]。因此p=a;与p=&a[0];等价。若p已经指向数组首元素,则p+1使得p指向同一个数组中的下一个元素,而不是将p的值简单的加1。例如数组元素是int型,每个元素占4个字节,则p+1意味着使p的值加4个字节,以使它指向下一个元素。因此p+1其实代表着p+1×4,即a[1]的地址;p+2则代表着p+2×4,即a[2]的地址。因此p+i则为a[i]的地址,*(p+i)则为a[i]。根据以上叙述,引用一个数组元素,可以用:(1)下标法:如a[i],p[i]等形式。(2)指针法:如*(p+i),*(a+i)等形式。说明:指针变量p可以执行p++运算,但a++是错误的用法。因为a是地址常量,不能进行自增运算。8.3.1一维数组与指针例8.3若有以下定义,则对a数组元素的正确引用是()inta[5],*p=a;A)*&a[5]B)a+2C)*(p+5)D)*(a+2)例8.4下面程序的运行结果是_________。#include<stdio.h>voidmain(){intx[]={0,1,2,3,4,5,6,7,8,9};ints=0,i,*p;p=&x[0];for(i=1;i<10;i+=2)s+=*(p+i);printf("sum=%d",s);}8.3.1一维数组与指针例8.5通过指针变量输入、输出a数组的10个元素。#include<stdio.h>voidmain(){int*p,i,a[10];p=a;for(i=0;i<10;i++)scanf("%d",p++);printf("\n");p=a;/*思考:若程序中无此语句,则结果如何*/for(i=0;i<10;i++,p++)printf("%5d",*p);printf("\n");}8.3.2二维数组与指针

二维数组可以看成是特殊的一维数组。例如:

inta[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}};a是一个数组名。a数组包含3个元素a[0],a[1],a[2]。而每一个元素又是一个一维数组,它包含4个元素。即a[0],a[1],a[2]都分别代表4个元素的一维数组。因此,a[0]是它所代表的一维数组中首元素的地址,即&a[0][0]。则a[0]+1代表&a[0][1]。a[1]是它所代表的一维数组中首元素的地址,即&a[1][0]。则a[1]+1代表&a[1][1]。

a代表数组首元素的地址,二维数组现在看成是三个元素的一维数组。因此,a是二维数组首行元素的地址。8.3.2二维数组与指针a[i][j]的地址可通过下列几种方式得到:(1)&a[i][j](2)a[i]+j(3)*(a+i)+j(4)&a[0][0]+4*i+j(5)a[0]+4*i+ja[i][j]元素可以用以下几种方式得到:(1)a[i][j](2)*(a[i]+j)

(3)*(*(a+i)+j)

(4)*(&a[0][0]+4*i+j)

(5)(*(a+i))[j]8.4字符串与指针C语言中字符串不能由字符变量来存储,只能通过字符数组或指针两种方式来访问。在第6章我们已经讲过了用数组来访问字符串,例如charstr[]="ABC“;。本节内容我们来介绍用指针访问字符串。定义一个字符指针,指向字符串中的字符。例如:

char*str1="ABC“;说明:1.str1是一字符指针,它是字符串首元素的地址,即指针str1指向字符A。它与字符数组不同。charstr2[]="ABC";,此时我们可以说将字符串ABC赋给了字符数组str2。使用字符指针和字符数组来访问字符串,如果是定义的同时赋值,那两者都可以。但如果是先定义后赋值,则两者是有区别的。

char*str1;str1="ABC";charstr2[4];str2="ABC";8.4字符串与指针2.用字符指针来访问的字符串,也可通过“%s”来整体输入或输出,也可使用字符串处理函数。例8.6

分析下列程序段的结果是____________。char*s="abcde";s+=2;printf("%d",s);printf("%s",s);例8.7下面程序的运行结果是____________。char*p=“abcdefgh”;p+=3;printf("%d\n",strlen(strcpy(p,"ABCD")));8.4字符串与指针例8.8设有两个字符串a、b,将a、b的对应字符的较大者存放在数组c的对应位置上。#include<stdio.h>#include<string.h>voidmain(){intk=0;chara[80],b[80],c[80]={'\0'},*p,*q;p=a;q=b;gets(a);gets(b);while(*p&&*q){if(*p<*q)c[k]=*q;elsec[k]=*p;p++;q++;k++;}if(*p!='\0')strcat(c,p);elsestrcat(c,q);puts(c);}8.4字符串与指针例8.9编写程序,判断输入的字符串是否是“回文”(顺读和倒读都一样的字符串称为回文,如level)。#include<stdio.h>#include<string.h>voidmain(){intn;chars[80],*p1,*p2;gets(s);n=strlen(s);p1=s;p2=s+n-1;while(p1<p2){if(*p1!=*p2)break;else{p1++;p2--;}}if(p1<p2)printf("不是回文\n");elseprintf("是回文\n");}8.5指针作函数参数

8.5.1指针变量作函数参数

指针变量作函数参数,传递的是地址,则对应的形参也应是能接收地址的变量,数组或指针变量。通过例题分析指针变量做函数参数时,变量的传递方式。例如:对输入的两个整数按大小顺序输出。#include<stdio.h>voidmain(){voidswap(int*p1,int*p2);inta,b;int*pointer_1,*pointer_2;scanf("%d,%d",&a,&b);pointer_1=&a;pointer_2=&b;if(a<b)swap(pointer_1,pointer_2);printf("\n%d,%d\n",a,b);}8.5.1指针变量作函数参数voidswap(int*p1,int*p2){inttemp;temp=*p1;*p1=*p2;*p2=temp;}思考:若swap函数做如下改动:voidswap(int*p1,int*p2){int*temp;temp=p1;p1=p2;p2=temp;}8.5.1指针变量作函数参数例8.10以下程序的运行结果_______________。#include<stdio.h>voidfun(int*x,int*y){printf("%d%d",*x,*y);*x=3+*y;*y=4+*x;}voidmain(){intx=1,y=2;fun(&y,&x);printf("%d%d",x,y);}8.5.2数组名作函数参数C程序中,当数组名作函数参数时,对应的形参也应是数组名或指针变量。在第7章我们已经讲过形参是数组名的情况,本节将介绍对应的形参为指针的情况。当数组名作实参时,传递的是数组首元素的地址,所以形参指针变量指向数组首元素。例8.11分析以下程序的运行结果是_________。#include<stdio.h>voidfun(int*b,intn,int*s){inti;*s=0;for(i=1;i<=n;i++)*s=*s+*(b+i);}voidmain(){intx=1,a[]={2,3,4,5,6};fun(a,3,&x);printf("\n%d",x);}8.5.2数组名作函数参数例8.12下面findmax函数将计算数组中的最大元素及其下标值。请编写findmax()函数。#include<stdio.h>voidfindmax(int*s,intt,int*k){}voidmain(){inta[10]={12,23,34,45,56,67,78,89,11,22},k;findmax(a,10,&k);/*变量k用来存放最大元素的下标*/printf("%d,%d\n",a[k],k);}findmax函数编写如下:voidfindmax(int*s,intt,int*k)/*s指针变量,指向数组a的首元素*/{intmax=*s,i;*k=0;for(i=0;i<t;i++,s++)if(max<*s){max=*s;*k=i;}}8.5.3字符指针作函数参数

字符指针作函数参数,参数传递原理与普通指针作函数参数相同。例8.13执行以下程序时,若从键盘输入"MyBook<回车>",则程序的运行结果是(

)。#include<stdio.h>charfun(char*s){if(*s<=’Z’&&*s>=’A’)*s+=32;return*s;}voidmain(){charc[80],*p;p=c;scanf("%s",p);while(*p){*p=fun(p);putchar(*p);p++;}printf("\n");}A)mYBookB)mybookC)myD)MyBook8.5.3字符指针作函数参数例8.14下面程序的功能是将字符串b复制到字符串a。请填空。#include<stdio.h>s(char*s,char*t){inti=0;while(________)_____________;}voidmain(){chara[20],b[20];scanf("%s",b);s(___________);puts(a);}8.5.3字符指针作函数参数例8.15下面conj函数是将两个字符串s1,s2连接起来。请编写函数conj()。#include<stdio.h>voidconj(char*p1,char*p2){}voidmain(){chars1[80],s2[80];gets(s1);gets(s2);conj(s1,s2);puts(s1);}编写的conj函数如下:voidconj(char*p1,char*p2){while(*p1)p1++;while(*p2){*p1=*p2;p1++;p2++;}*p1='\0';}8.5.3字符指针作函数参数例8.16编写函数,将字符串中的第m个字符开始的全部字符复制成另一个字符串。#include<stdio.h>voidcopy(char*p1,char*p2,intm){}voidmain(){chars1[80],s2[80];intm;scanf("%d",&m);gets(s2);copy(s1,s2,m);puts(s1);}编写的copy函数如下:voidcopy(char*p1,char*p2,intm){p2=p2+m-1;while(*p2!='\0'){*p1=*p2;p1++;p2++;}*p1='\0';}8.6返回指针值的函数

返回指针值的函数的定义形式为:类型名*函数名(参数表列);例如:int*func(intx,inty){int*p;if(x>y)p=&x;elsep=&y;returnp;}

定义func函数的返回值的类型是指向整型变量的指针。因此,程序中return后的表达式也应该是一个指向整型变量的指针。8.7指针数组和指向指针的指针

8.7.1指针数组

一个数组,若其元素均为指针类型数据,称为指针数组。定义形式:类型名*数组名[数组长度];例如:int*p[4];p是一个含4个元素的数组,而且每个元素都是指向整型数据的指针。注意:int(*p)[4];p是一个指针变量,指向一个含4个元素的一维数组。若有说明:char*language[]={“FORTRAN”,”BASIC”,”PASCAL”,”JAVA”,”C”};则language[2]是一指针,指向字符串PASCAL的首元素。因此,该元素的值是一地址,*language[2]的值是p。例8.17有以下程序,程序运行后的输出结果是(

)。

#include<stdio.h>voidmain(){char

*a[]={"abcd","ef","gh","ijk"};

inti;

for(i=0;i<4;i++)

printf(“%c”,*a[i]);

}A)aegi

B)dfhk

C)abcd

D)abcdefghijk8.7.2指向指针的指针

定义形式:类型名**指针变量名例如:inti=3,*p1,**p2;p1=&i;p2=&p1;

在以上程序代码中,*p1和i等价,*p2、p1、&i等价,**p2、*p1、i等价。8.7.2指向指针的指针例8.18分析以下程序段。char*name[]={"Followme","BASIC","GreatWall","FORTRAN","Computerdesign"};char**p;p=name+2;printf("%o",*p);printf("%s\n",*p);例8.19下面程序的运行结果是()。#include<stdio.h>voidmain(){intx[5]={2,4,6,8,10},*p,**pp;p=x;pp=&p;printf("%d",*(p++));

温馨提示

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

最新文档

评论

0/150

提交评论