9计算机二级语言-指针_第1页
9计算机二级语言-指针_第2页
9计算机二级语言-指针_第3页
9计算机二级语言-指针_第4页
9计算机二级语言-指针_第5页
已阅读5页,还剩55页未读 继续免费阅读

下载本文档

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

文档简介

第9章指针3/20/202411引例●三人欲借用某旅馆的一个房间,A先到达,在旅馆的效劳台登记房间,房号是5818,然后A打通知了B,但是没有通知C,问B和C怎么找到A?B可以直接到5818房间找到AC到旅馆效劳台查询A的房号为5818,然后再找到A2§9.1地址和指针的概念●一、变量的地址计算机中,数据存储在内存中.内存可以划分为假设干个存储单元,每个存储单元可以存放8位bit二进制数,即1个字节byte.内存当中采用线性地址编码,每个单元具有唯一一个地址编码.1、变量的地址:

系统为变量单元分配的内存地址——一个无符号整数inta;floatb;a=3;b=5;a3AB0b3AC02、变量的属性存储内容:数据值空间大小:数据类型

空间位置:地址生存周期:存储类别353§9.1地址和指针的概念二、变量的访问方式1、直接访问2、间接访问:定义一个变量p,存放a的地址,通过p来访问aintafloatba=3;b=5;假设将p中地址换成3AC0(B的地址),那么可以通过p来访问B3a3AB05b3AC03AB0p4§9.1地址和指针的概念三、指针变量指针变量是存放地址的变量;如何定义p?如何获得变量a的地址,即p中的内容?如何通过p来访问a?如:p为指针变量,它存放整型变量a的首地址,那么称指针变量p指向整型变量a。3a3AB05b3AC03AB0p5§9.2指针变量的定义与引用●一、定义方法类型符*指针变量名

指针变量的类型:指针所指向内存单元中存放的数据的类型.int*p1,*p2;char*ps;float*pf1,*pf2;(1)用变量地址给指针变量赋值(使用到地址符&)指针说明符●二、指针变量的赋值

指针变量的值为地址,是个无符号整数.

不能直接将一个整数常量赋值给指针变量int*p1p1=0X1234int*p,a,b;p=&a;注:变量的类型必须与指针变量类型相同(2)用相同类型的指针变量赋值int*p1,*p2,a;p1=&a;p2=p1;注:假设不赋值,那么指针变量的值是随机的.(3)赋空值NULLint*p1;p1=NULL;或p1=0;int*p1=NULL;floata;float*p2=&a;charch,*p3=&ch;6§9.2指针变量的定义与引用●三、指针变量的应用1.两个有关的运算符:*,&

形式:&任意变量

/*取变量地址运算符*/

*指针变量

/*指针运算符*/含义:

&a表示变量a所占据的内存空间的首地址;*p表示指针变量p所指向的内存单元中的数据.如果:p=&a;*pa①将指针变量指向被访问的变量如:inta=5,*p,b;p=&a;应用:通过指针变量指向所指的变量,即通过p访问a;〔步骤〕②访问所指变量

取内容:b=*p;printf(“%d\n”,b);③存内容:*p=100;例9-1voidmain()

{inta=5,b=3;int*p;p=&a;b=*p+5;printf(“%d\n”,b);*p=4;printf(“%d,%d\n”,a,*p);}注意:*p假设出现在“=”右边或其他表达式中那么为取内容;*p假设出现在“=”左边那么存内容,即向内存中写数据.7§9.2指针变量的定义与引用●三、指针变量的应用2.运算规那么&,*优先级相同,且为右结合※与++.--.!等单目运算符优先级相同※高于算术运算符*,/,%①printf():从右到左输出②(*q)++和*(q++)两者不同

内容++地址++例9-1voidmain()

{inta=2,*p=&a,*q=&a;printf(“%d,%d\n”,*p++,*(q++));p=&a,q=&a;printf(“%d,%d\n”,*p,(*q)++);}假设有:inta=5,*p=&a;写出下面表达式的结果,并找出等价的表达式&*p*&a(*p)++&aa*p++*(p++)a++思考:以下表达式是什么意思?&*p*&a牢记以下等价式:int*p=&a;&*pp*&aa&ap*pa结果:2232要求:*后一定是指针变量;…...…...200020002002200420062apq20008例9-2#include<stdio.h>voidmain(){inta,b,c;int*pa,*pb,*pc;pa=&a;pb=&b;pc=&c;scanf(“%d%d”,pa,pb);printf(“a=%d,b=%d\n”,*pa,*pb);c=a+b;printf(“c=%d\n”,*pc);*pc=a+*pb;printf(“c=%d\n”,c);c=*pa**pb;printf(“c=%d\n”,c);c=++*pa+(*pb)++;printf(“c=%d\n”,c);c=(*pa)+++*pb;printf(“c=%d\n”,c);printf(“a=%d,b=%d\n”,a,b);}假设输入为:239例9-3交换两个数a,b的值#include<stdio.h>voidmain(){inta=5,b=8;intt;printf(“a=%d,b=%d\n”,a,b);t=a;a=b;b=t;printf(“a=%d,b=%d\n”,a,b);}例9-3交换两个数a,b的值#include<stdio.h>voidmain(){inta=5,b=8;int*pa=&a,*pb=&b;intt;printf(“a=%d,b=%d\n”,a,b);t=*pa;*pa=*pb;*pb=t;printf(“a=%d,b=%d\n”,a,b);}10§9.2指针变量的定义与引用●四、指针变量作函数参数例9-4编写一个函数实现两个数的交换#include<stdio.h>voidswap(intx,inty){intt;t=x;x=y;y=t;}voidmain(){inta=3,b=5;swap(a,b);printf(“%d%d\n”,a,b);}#include<stdio.h>voidswap(int*x,int*

y){intt;t=*

x;*

x=*

y;*

y=t;}voidmain(){inta=3,b=5;swap(&a,&b);printf(“%d%d\n”,a,b);}voidswap(int*x,int*

y){int*t;t=x;x=y;

y=t;}voidswap(int*x,int*

y){int*t;

*

t=*

x;*

x=*

y;*

y=*

t;}*t未赋初值,系统会随机给值,可能指向一个已有数据的存储单元,再执行交换,就会破坏已有数据。11例9-5输入a,b,c三个数,按从大到小输出#include<stdio.h>voidswap(int*x,int*y){intt;t=*x;*x=*y;*y=t;}voidmain(){inta,b,c;printf(“enterdataa,b,c:”);scanf(“%d%d%d”,&a,&b,&c);if(a<b)swap(&a,&b);if(a<c)swap(&a,&c);if(b<c)swap(&b,&c);printf(“a=%d,b=%d\n”,a,b);}12§9.3指针和数组●一、一维数组与指针1.数组是连续存放假设干数据的集合.2.数组名就是指向这个数组第1个元素的指针(首地址)例如:inta[10],*p;那么p=ap=&a[0];3.某一元素地址:p=&a[i];引用该元素:*p

a[i]注意:数组名a(数组的指针)与指向数组首地址的指针变量p不同,a是地址常量不能赋值,也不能进行自增自减运算。4.数组元素地址在内部实现时,统一按照”基地址+位移”方式处理:如:aa+1a+i故元素的地址可以表示为:p+ia+i(数组指针)5.数组元素的内容可以表示为:a[i](数组下标)*(p+i)*(a+i)(指针表示)13例9-6读程序写出结果#include<stdio.h>voidmain(){inta=3,b=5;int*p=&a;printf(“%d\n”,*p);*p=4;p=&b;printf(“%d\n”,*p);*p=6;printf(“%d,%d\n”,a,b);}例9-6读程序写出结果#include<stdio.h>voidmain(){inti,a[5];int*p;for(i=0;i<5;i++){p=&a[i];a[i]=i;printf(“%3d”,*p);}printf(“\n”);}例9-6读程序写出结果#include<stdio.h>voidmain(){inti,a[5];int*p=a;for(i=0;i<5;i++,p++){

*p=i;printf(“%3d”,a[i]);}printf(“\n”);}14§9.3指针和数组●一、一维数组与指针数组指针.指针变量.数组元素之间的关系设有inta[10],*p=a;那么地址关系内容关系15§9.3指针和数组●一、一维数组与指针例9-7读程序,理解书写上的变化#include<stdio.h>voidmain(){inti,a[5];printf(“input5numbers:\n”);for(i=0;i<5;i++)scanf(“%d”,&a[i]);printf(“outputthesenumbers:\n”);for(i=0;i<5;i++)printf(“%d”,a[i]);printf(“\n”);}scanf(“%d”,a+i);scanf(“%d”,p+i);printf(“%d“,*(a+i));printf(“%d“,*(p+i));int*p=a;16§9.3指针和数组●二、指针的运算1.赋值运算:如:p=&x;p=NULL;p=a;注:指针类型相同2.加减运算:用法:指针+(-)整数如:a+ip+i3.指针相减的运算,求两地址的间距:

指针–指针如p-a注:只能用于数组元素的引用,注意下标的范围.注:两指针类型相同,并指向同一连续存储区域.4.移动指针运算:如p++p--注:对数组名不能实行移动5.指针比较运算:指针运算符指针如:p<a比较地址注:2~5的运算通常应用于指向数组的指针17§9.3指针和数组●二、指针的运算例9-8将a数组中的内容复制到b数组中#include<stdio.h>#defineM7voidmain(){inti,a[M]={23,15,50,3,21,20,35};intb[M];for(i=0;i<M;i++)b[i]=a[i];printf(“outputthesenumbers:\n”);for(i=0;i<5;i++)printf(“%d”,b[i]);printf(“\n”);}printf(“%d”,*q++);结果如何?18§9.3指针和数组●三、数组的指针与函数参数形式一:voidf(intx[],intn){}voidmain(){inta[10];……f(a,10);}数组名作为函数参数,实参与形参对应关系可归纳为四种情况:形式二:voidf(int*x,intn){}voidmain(){inta[10];……f(a,10);}形式三:voidf(int*x,intn){}voidmain(){inta[10],*p=a;……f(p,10);}形式四:voidf(intx[],intn){}voidmain(){inta[10],*p=a;……f(p,10);}19§9.3指针和数组例9-9编写一个函数求一维数组最大元素以及下标(使用指针).:数组首地址为p,元素个数为n.(作函数参数)结果:下标k(函数返回值)intmax_array(int*p,intn)设最大值放在max中,那么初始状态为:max=*p,k=0;如果*(p+i)>max那么max=*(p+i),k=i;#include<stdio.h>intmax_array(int*p,intn){intk=0,i,max=*p;for(i=1;i<n;i++)

if(*(p+i)>max){max=*(p+i);k=i;}returnk;}voidmain(){inta[10]={23,43,52,23,5,22,33,35,96,34};inti,*p=a,k;for(i=0;i<10;i++)printf(“%5d”,*(p+i));k=max_array(a,10);printf(“max=a[%d]=%d\n”,k,*(p+k));}p++,i++)*p*p*p++;20§9.3指针和数组例9-10编写一个函数将一维数组倒置存放(使用指针).:数组首地址为p,元素个数为n.(作函数参数)结果:倒置后的一维数组函数定义:intinverse(inta[],intn)或intinverse(int*p,intn)算法:1.令p指向数组开始,q指向数组结束;#include<stdio.h>voidinverse(int*p,intn){int*q,t;q=p+n-1;while(p<q){t=*p;*p=*q;*q=t;p++;q--;}}voidmain(){inta[]={1,3,5,7,9};intk,*p=a;for(k=0;k<5;k++)printf(“%4d”,*p++);putchar(‘\n’);inverse(a,5);for(p=a,k=0;k<5;k++)printf(“%4d”,*p++);putchar(‘\n’);}voidinverse(inta[],intn){int*q,t,i=0;q=a+n-1;while(a+i<q){t=*(a+i);*(a+i)=*q;*q=t;i++;q--;}}2.交换两个单元内容;3.两个指针向中央靠拢;4.重复2和3,直到p>=q;21§9.3指针和数组例9-11求某班某门课的平均成绩,统计超过平均值的人数(使用指针完成)分析:1.令p指向score(存放成绩的数组)的开始;2.通过移动指针求和;5.不移动指针但通过指针判断各单元的内容是否大于平均值;并记数.#include<stdio.h>#defineN30voidmain(){floatscore[N],*p;floatv,s=0;intk,num=0;for(p=score,k=0;k<N;k++){scanf(“%f”,p);s+=*p;p++;}v=s/N;

for(p=score,k=0;k<N;k++)if(*(p+k)>v)num++;printf(“average=%.2f,\num%d\n”,v,num);}3.求平均值;4.令p重新指向score的开始;2201020111212122231323a⑴二维数组的地址例如:inta[3][4];

①二维数组名a是数组的首地址。②二维数组a包含三个行元素:a[0]、a[1]、a[2]

。a[0]a[1]a[2]a三个行元素的地址分别是:a、a+1、a+2。而a[0]、a[1]、a[2]也是地址量,是一维数组名,即*(a+0)、*(a+1)、*(a+2)是一维数组首个元素地址。●四、二维数组与指针

a+1a+2§9.3指针和数组23⑵二维数组元素的地址

a[0]、a[1]、a[2]是一维数组名,所以a[i]+j是数组元素的地址。数组元素a[i][j]的地址可以表示为以下形式:&a[i][j]、a[i]+j、*(a+i)+j01020111212122231323a[0]数组a[1]数组a[2]数组a[2]+1a[2]+2a[2]+3a[0]+1a[0]+2a[0]+3§9.3指针和数组●四、二维数组与指针

24⑶二维数组元素的表示法数组元素可用以下形式表示:a[i][j]、*(a[i]+j)、*(*(a+i)+j)

a

是二维数组,根据C的地址计算方法,a经过两次

*

操作才能访问到数组元素。所以

*

a是

a[0],*

*

a才是a[0][0]。

a[0]是a[0][0]的地址,*a[0]是a[0][0]。01020111212122231323a[0]a[1]a[2]a●四、二维数组与指针

§9.3指针和数组25⑷指向二维数组元素的指针变量【例9-12】用指向数组元素的指针变量输出数组元素。main(){inta[3][4]={{0,1,2,3},{10,11,12,13},{20,21,22,23}},i,j,*p;for(p=a[0],i=0;i<3;i++){for(j=0;j<4;j++)printf("%4d",*(p+i*4+j));/*元素的相对位置为i*4+j*/printf("\n");}}这种指针变量的定义及使用与指向一维数组元素的

指针变量是相同的,用它存放二维数组元素的地址。01020111212122231323ap§9.3指针和数组●四、二维数组与指针

26⑸指向一维数组的指针变量

指向一维数组指针变量的定义形式:数据类型标识符(*变量名)[元素个数]

“*”表示其后的变量名为指针类型,[元素个数]表示目标变量是一维数组,并说明一维数组元素的个数。由于“*”比“[]”的运算级别低,“*变量名”作为一个说明部分,两边必须加括号。“数据类型标识符”是定义一维数组元素的类型。●四、二维数组与指针

§9.3指针和数组27【例9-13】用指向一维数组的指针变量输出数组元素。main(){inta[3][4]={{0,1,2,3},{10,11,12,13},{20,21,22,23}};int(*lp)[4],i,j;for(lp=a,i=0;i<3;i++){for(j=0;j<4;j++)printf("%4d",*(*(lp+i)+j));printf("\n");}}01020111212122231323alplp+1lp+2

0123

10111213

20212223§9.3指针和数组●四、二维数组与指针

28【例9-13】用指向一维数组的指针变量输出数组元素。main(){inta[][4]={0,1,2,3,10,11,12,13,20,21,22,23};int(*lp)[4],j;for(lp=a;lp<a+3;lp++){for(j=0;j<4;j++)printf("%4d",*(*lp+j));printf("\n");}}01020111212122231323alplplplp

0123

10111213

20212223

●四、二维数组与指针

§9.3指针和数组29§9.4指针和字符串一、字符串指针C语言中字符串是以’\0’为结尾的字符序列;用字符数组存放字符串(即将以’\0’为结尾字符数组看作字符串);字符串指针就是字符数组的首地址;如:chara[]=“Apple”;charb[]={‘C’,’h’,’i’,’n’,’a’,’\0’}int*p,*q;p=123;q=&123;*p=123;定义:char*指针变量char*p,*q=“Language”;p=“Thisisabook.”;二、字符串指针变量char*p,c[10];p=c;注意:p是指向字符串首地址,不是存放字符数组30§9.4指针和字符串例9-14逆序打印字符串算法:设字符串为q;令p指向字符串结尾;

打印字符*p,并将p向前移动;直到p移到字符串首q位置.#include<stdio.h>voidmain(){char*p,*q=“Language”;

for(p=q;*p!=‘\0’;)p++;for(p--;p>=q;p--)putchar(*p);putchar(‘\n’);}#include<stdio.h>#include<string.h>voidmain(){char*p,*q=“Language”;

intn;n=strlen(q);p=q+n;for(p--;p>=q;p--)putchar(*p);putchar(‘\n’);}31§9.4指针和字符串例9-15编写一个函数判断一个字符串是否是回文(顺序与逆序相同):字符串指针变量为p(函数参数)结果:是(1),否(0)(返回值)intishuiwen(char*p){char*q=p;while(*q!=‘\0’)q++;q--;while(p<q)if(*p==*q){p++;q--;}elsereturn0;return1;}算法:1.令q指向最后一个字符;2.假设*p=*q,那么两指针向中间靠拢,直到p>=q,返回1;3.假设*p!=*q,那么返回0.intishuiwen(char*p){char*q=p;while(*q)q++;q--;while(p<q)if(*p++!=*q--)return0;return1;}32§9.4指针和字符串三、字符数组与字符指针变量的比较chara[]=“Ilovethisgame”,*p=a;1.存储的内容不同:字符数组可以存字符串,存的是字符;字符指针变量存的是字符串在内存中首地址;chara[10],*p;p=“china”;a=“china”;3.当没有赋值时:字符数组名代表了一个确切的地址;字符指针变量中的地址是不确定的.2.赋值方式不同:字符数组只能对各元素赋值;(一次只能赋一个字符)字符数组指针只赋值一次,赋的是数组首地址.Ilovethisgame数组a变量p300A300Achara[10],*p;scanf(“%s”,a);scanf(“%s”,p);33§9.4指针和字符串三、字符数组与字符指针变量的比较chara[]=“Ilovethisgame”,*p=a;4.字符数组名不是变量,不能改变值;字符指针变量可以改变值;chara[10],*p;a++;p++;6.字符串指针变量的应用:例如:可以用指针变量指向一个格式字符串,在printf中直接使用此指针变量.5.可以象数组那样使用下标引用字符数组指针变量所指字符串中的字符.char*p=“abcd”;putchar(p[3]);p[2]=‘x’;char*fmt=“a=%d,b=%d,c=%d\n”;printf(fmt,a,b,c);

printf(“a=%d,b=%d,c=%d\n”,a,b,c);34§9.4指针和字符串三、字符数组与字符指针变量的比较7.以下的形式那些是正确的:chard[10],*q=d;intx=5,*p=&x;d=“apple”;scanf(“%s”,d);printf(“%s”,d);q=“pear”;scanf(“%s”,q);printf(“%s”,q);*q=“orange”;printf(“%s”,*q);*p=100;scanf(“%d”,p);printf(“%d”,*p);×√√√√√√√××√35指针数组定义的一般形式:数据类型标识符

*数组名[元素个数];在这个定义中由于“[

]”比“*”的优先级高,所以数组名先与“[元素个数]”结合,形成数组的定义形式,“*”表示数组中每个元素是指针类型,“数据类型标识符”说明指针的目标变量的数据类型。例如:int*ip[10];char*cp[5];1.指针数组的定义

指针数组就是数组中的每个元素均为指针类型

§9.5指针数组362.指针数组初始化

cpC数组cp[0]Fortran\0cp[1]COBOL\0cp[2]BASIC\0cp[3]Pascal\0例如:charc[4][8]={"Fortran","COBOL","BASIC","Pascal"};char*cp[4]={c[0],c[1],c[2],c[3]};/*VC中合法,TC中不合法*/char*str[5]={"int","long","char","float","double"};str[0]int\0str[1]long\0str[2]char\0str[3]float\0str[4]double\0§9.5指针数组37【例9-16】用0~6分别代表星期日至星期六,当输入其中任意

一个数字时,输出相应英文单词。main(){char*weekname[7]={"Sunday","Monday","Tuesday",

"Wednesday","Thursday","Friday","Saturday"};intweek;printf("EnterweekNo.:");scanf("%d",&week);if(week>=0&&week<7)

printf("weekNo.%d——%s\n",week,weekname[week]);}3.利用字符指针数组处理多个字符串

利用字符指针数组处理长度不等的字符串,可节省存储空间。

§9.5指针数组381.二级指针变量的定义

整型值整型变量整型变量地址一级指针变量一级指针变量地址二级指针变量如果一个指针的目标变量是一个指针类型变量,那么此指针为指向指针的指针变量,也称为多级指针变量。二级指针变量定义的一般形式:数据类型标识符**指针变量名;其中“**指针变量名”相当于*(*指针变量名〕,在括号中定义了一个指针变量,括号外的“*”,说明指针变量〔即二级指针〕的目标变量是一个指针类型数据,“数据类型标识符”是目标变量〔即一级指针〕所指向的数据的类型,也就是最终目标变量的类型。例如:inta,*p,**pp;§9.5多级指针392.二级指针变量初始化

a的内容a&ap&ppp例如:inta,*p=&a,**pp=&p;、*p、**pp、*pp§9.5多级指针40【例9-17】利用二级指针输出字符串。main(){staticchar*name[]={"Zhang","Wang","Li",""};char**pp=name;while(**pp!='\0')printf("%s\n",*pp++);}nameZhang\0Wang\0Li\0\0pppppppppppppp*(*pp+1)=h、*(*pp+2)=aZhangWangLi§9.5多级指针411,一维数组的指针作函数参数

一.数组的指针作函数参数

2,二维数组的指针作函数参数

由于指向二维数组的指针分为行指针和元素指针,所以他们作为函数参数的形式也不同。

①二维数组的行指针作函数参数例如被调函数abc的定义形式有以下三种:voidabc(intb[2][4]){……}voidabc(intb[][4]){……}voidabc(int(*b)[4]){……}在主调函数有如下定义:inta[2][4],(*p)[4]=a;那么调用abc函数时可用abc(a)或abc(p)§9.5指针与函数42【例9-18】用函数输入输出整型二维数组,函数的形参为行指针。voidinarr(int(*p1)[4],intm)/*可改写为voidinarr(intp1[][4],intm)*/{inti,j;for(i=0;i<m;i++)for(j=0;j<4;j++)scanf("%d",*(p1+i)+j);}voidoutarr(int(*p2)[4],intm)/*可改写为voidoutarr(intp2[3][4],intm)*/{inti,j;for(i=0;i<m;i++){for(j=0;j<4;j++)printf("%6d",p2[i][j]);printf("\n");}}一.数组的指针作函数参数

§9.5指针与函数voidmain(){inta[3][4],(*p)[4];p=a;

inarr(a,3);outarr(p,3);}43一.数组的指针作函数参数

2,

二维数组的指针作函数参数

②指向二维数组元素的指针作函数参数指向二维数组元素的指针作函数参数时,是利用二维数组元素按行连续存储的的特点,访问数组的每一个元素。被调函数的形参必须定义为指向二维数组元素的指针变量。例如被调函数abc的定义形式如下:voidabc(int*b){……}在主调函数有如下定义:inta[2][4],*p=a[0];那么调用abc函数时可用abc(a[0])、abc(&a[0][0])或abc(p)§9.5指针与函数44【例9-19】用函数输入输出整型二维数组,函数的形参为指向二维数组元素的指针。

voidinarr(int*p1,intm,intn){inti,j;for(i=0;i<m;i++)for(j=0;j<n;j++)scanf("%d",p1+n*i+j);}voidoutarr(int*p1,intm,intn){inti,j;for(i=0;i<m;i++){for(j=0;j<n;j++)printf("%6d",*(p1+n*i+j));printf("\n");}}一.数组的指针作函数参数

main(){inta[3][4],*p;p=&a[0][0];inarr(a[0],3,4);outarr(p,3,4);}§9.5指针与函数45二、带参数的主函数1.带参数的主函数的定义

main(intargc,char*argv[]){……}

main函数只能有两个形参,并且这两个形参的类型也是固定的。第一个形参必须是整型变量,第二个形参可以定义为字符型指针数组,也可以定义为二级字符指针变量,因此也可以写成

main(int

argc,char**argv)§9.5指针与函数46二、带参数的主函数2.带参数的主函数的调用

带参数的主函数调用形式:可执行文件名参数1参数2……参数n在DOS系统提示符下键入的这一行字符称为命令行。可执行文件名称为命令名,其后的参数称为命令行参数,命令名与各参数之间用空格进行分隔。要调用带参数的主函数必须在操作系统环境下进行。假设C语言源程序文件file1.c,经过编译、连接生成一个可执行文件file1.exe。在DOS系统提示符后键入可执行文件名file1,即可执行该程序。§9.5指针与函数47二、带参数的主函数3.主函数参数的作用

argc称作参数计数器,它的值是包括命令名在内的参数个数。argv指针数组的作用是存放命令行中命令名和每个参数字符串的首地址。C:\>file1onetwothreeargv[0]file1\0argv[1]one\0argv[2]two\0argv[3]three\0argvargc4§9.5指针与函数48C:\>二、带参数的主函数【例9-20】显示命令行参数程序。voidmain(intargc,char*argv[]){inti=0;while(--argc>0)printf("%s\n",argv[++i]);}file1onetwothree

onetwothree注意:命令行参数所传送的数据全部都是字符串。即便传送的是数字,也是按字符串方式传送给主函数。程序中使用这些参数时,还需要将数字字符串转换成数值型数据。C语言标准库函数提供了一些相关的数据类型转换函数,如atoi()、atof(),使用时应包含头文件

stdlib.h

。49三、指针型函数1.指针型函数的定义

指针型函数定义的一般形式:数据类型标识符*函数名〔形式参数表〕{……}其中函数名前的“*”表示函数的返回值是一个指针类型,“数据类型标识符”是指针所指向的目标变量的类型。如果一个函数的返回值是指针,那么称此函数为指针型函数。§9.5指针与函数50char*subcut(char*a,ints,intlen){staticcharsubstr[SIZE+1];/*substr用于存放子串*/intn;char*ps;ps=substr;if(s<0||s>=strlen(a)||len<1)printf("dataerror\n");/*数据错,子串为空*/elsefor(n=0,a+=s;n<len&&*a!='\0';n++)*ps++=*a++;*ps='\0';/*复制结束参加字符串结束标志*/return(substr);}三、指针型函数【例9-21】编制一个函数,其功能是从字符串中指定位置s开始截取一个长度为len的子串。思路:在截取子串函数sutcut中需要从主调函数传送3个数据,源字符串、截取位置s、长度len。在形参中定义一个指针变量a接收源字符串的首地址,在函数中再定义一个存储类型为static的字符数组substr用于存放子串,指针变量ps指向substr数组。在截取子串的过程中,如果起始位置s小于0或大等于源串那么子串为空,如果截取长度len小于1子串也为空;否那么循环复制子串,直到复制了len个字符或从源串读到'\0'结束。最后函数将返回substr字符数组的首地址。假设起始位置s小于0或大等于源串长度或截取长度len小于1从第s个字符开始,复制len个字符

§9.5指针与函数51三、指针型函数2.指针型函数定义时应注意的问题

指针函数中return的返回值必须是与函数类型一致的指针。②

返回值必须是外部或静态存储类别的变量指针或数组指针,以保证主调函数能正确使用数据。

§9.5指针与函数52四、指向函数的指针1.函数指针变量的定义

函数指针变量定义的一般形式:数据类型标识符(*函数指针变量名)();其中“*函数指针变量名”必须用圆括号括起来,否那么就成为声明一个指针型函数了。在定义中“(*函数指针变量名)”右侧的括号“()”表示指针变量所指向的目标是一个函数,“数据类型标识符”是定义指针变量所指向的函数的类型。例如:int(*p)();/*p是一个指向整型函数的指针变量*/float(*q)();/*q是一个指向单精度实型函数的指针变量*/在C语言中,函数名具有与数组名类似的特性,数组名代表数组的首地址,函数名代表函数的起始地址〔即该函数的程序代码段在内存中所占用的存储空间的首地址,也称函数入口〕。因此也可以把函数名赋给一个函数指针变量,使其成为指向该函数的指针变量。函数名那么可以看成是函数指针常量。§9.5指针与函数53四、指向函数的指针2.用函数指针变量调用函数

用函数指针变量调用函数的一般形式:

(*函数指针变量名)(实参表);

由于优先级不同“*函数指针变量名”必须用圆括号括起来,表示间接调用指针变量所指向的函数;右侧括号中为传递到被调函数的实参。

函数指针与变量指针的共同之处是都可以做间接访问。变量指针指向内存的数据存储区,通过间接存取运算访问目标变量;函数指针指向内存的程序代码存储区,通过间接存取运算使程序流程转移到指针所指向的函数入口,取出函数的机器指令并执行函数,完成函数的调用。

§9.5指针与函数54四、指向函数的指针main(

){intmax(int,int

),a,b,c;/*声明被调用的目标函数max*/int(*p)(int,int);/*定义p为指向整型函数的指针变量*/p

=

max;/*用指针变量存储函数入口地址*/scanf(“%d%d”,&a,&b);c=(*p)(a,b);/*用指针变量调用函数*/printf(“max=%d”,c);}max(in

温馨提示

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

评论

0/150

提交评论