c语言程序设计课件 第7章指针_第1页
c语言程序设计课件 第7章指针_第2页
c语言程序设计课件 第7章指针_第3页
c语言程序设计课件 第7章指针_第4页
c语言程序设计课件 第7章指针_第5页
已阅读5页,还剩121页未读 继续免费阅读

下载本文档

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

文档简介

1第7章

指针2知识回顾-计算机的主要工作流程101010110101101111110111…001110111100010110001111CPU(中央处理器)3内存的组织结构内部存储器,是由存储单元组成的。它的特点是存储单元是线性连续的。存储单元的最小单位是字节。4如何找到要存储的数据?为了访问内存中的某个存储单元,我们为每一个内存的基本存储单元编号,通过这个编号就可以访问该单元所存放的数据内容。这种编号称为内存地址。5变量同地址的关系系统给变量分配内存单元,变量在内存中可能会占用几个连续的字节,起始字节的内存单元的地址,就是变量的地址。20076还有其它的什么样的操作方式?77.1指针的基本概念指针:一个变量的地址称为该变量的指针。指针变量:若一个变量专用于存放另一个变量的地址(指针),则该变量称为指针变量。8几个概念-指针、指针变量的关系…...…...2000200420062005整型变量i5变量i_pointer2001200220032000指针指针变量变量的内容变量的地址指针变量变量变量地址(指针)变量值指向地址存入指针变量9直接访问与间接访问直接访问:按变量地址存取变量值间接访问:通过存放变量地址的变量去访问变量例

i=3;-----直接访问指针变量…...…...2000200420062005整型变量i10变量i_pointer20012002200320003例*i_pointer=5;-----间接访问5107.1.2指针变量的定义一般形式:

类型标识符*变量名;例如:int*ptr1,*ptr2;指针变量的类型:指明了该指针指向的内存空间所存储的数据类型。

11定义指针变量时要注意的问题:定义中的“*”表示所定义的变量是指针变量,但指针变量名是ptr1、ptr2,而非*ptr1、*ptr2。变量名ptr2前面的“*”不能省略,如果写成:int*ptr1,ptr2;则ptr2被定义为整型变量,而非整型指针变量。12要注意的问题指针变量只能指向定义时所规定类型的变量。这个规定的类型称为该指针变量的“基类型”。例如:int*ptr1定义指针变量后,并未确定该变量指向何处。也就是说该变量的值是不确定的。在引用指针变量前必须首先让它指向一个变量,这一点非常重要。137.1.3指针变量的引用指针运算符(“&”和“*”

)“&”(地址运算符):取变量的存储地址。“*”(引用运算符):是取指针所指向变量的内容。例:例如:&a是求变量a的地址。

14int

main(void){ inta,b; int*pointer_1,*pointer_2; a=100;b=10; pointer_1=&a; pointer_2=&b; printf(“%d,%d\n”,a,b); printf(“%d,%d\n”,*pointer_1,*pointer_2);}通过指针变量访问整型变量15对“&”和“*”运算符说明:如果已执行了语句pointer_1=&a;(1)&*pointer_1的含义是什么?“&”和“*”两个运算符的优先级别相同,但按自右向左方向结合。因此,&*pointer_1与&a相同,即变量a的地址。如果有pointer_2=&*pointer_1;它的作用是将&a(a的地址)赋给pointer_2,如果pointer_2原来指向b,经过重新赋值后它已不再指向b了,而指向了a。1617(2)

*&a的含义是什么?

先进行&a运算,得a的地址,再进行*运算。*&a和*pointer_1的作用是一样的,它们都等价于变量a。即*&a与a等价。182.指针的初始化和赋值运算指针的赋值运算:就是把地址赋值给指针变量。可以是以下三种方式:用取地址运算符,把地址值赋值给指针变量。把指针变量的值赋给另一个指针变量。给指针变量赋值为符号常量NULL。如:inti,*pi;pi=&i;

如:inti,*pa,*pb;pa=&i;pb=pa;如:int*pi;pi=NULL;

19说明:⑴在定义指针变量时,可以立即将一个地址值赋给指针变量,这就是指针变量的初始化。指针变量的初始化也是指针的赋值运算。如:floatflt,*f_ptr=&flt;

注意:这不是给*f_ptr赋值,而是给指针变量f_ptr赋初值⑵指针变量间的赋值和引用应保证基类型相同。若有定义:int*p,i;float*q,x;则:q=&i;╳p=&x;╳20例main(){inti=10;

int*p;

*p=i;

printf(“%d”,*p);}危险!例

main(){inti=10,k;

int*p;

p=&k;*p=i;

printf(“%d,%d”,*p,k););}…...…...2000200420062005整型变量i10指针变量p200120022003随机21例:指针的概念int

main(void){

inta;

int*pa=&a;a=10;printf("a:%d\n",a);printf("*pa:%d\n",*pa);printf("&a:%x(hex)\n",&a);printf("pa:%x(hex)\n",pa);printf("&pa:%x(hex)\n",&pa);}运行结果:a:10*pa:10&a:f86(hex)pa:f86(hex)&pa:f88(hex)…...…...f86f8af8cf8b整型变量a10指针变量paf87f88f89f8622例输入a和b两个整数,按先大后小的顺序输出a和b。#include<stdio.h>int

main(){int*p1,*p2,*p,a,b;

scanf(“%d,%d”,&a,&b);

p1=&a;p2=&b;

if(a<b)

{p=p1;p1=p2;p2=p;}

printf(“a=%d,b=%d\n\n”,a,b);

printf(“max=%d,min=%d\n”,*p1,*p2);return0;}23运行情况如下:5,9↙a=5,b=9max=9,min=5当输入a=5,b=9时,由于a<b,将p1和p2交换。交换前的情况见图(a),交换后见图(b)。24257.1.4指针变量作为函数参数同整数、浮点数等其它类型的数据一样,指针也可以用作函数参数。格式:函数的返回数据类型

函数名(指针所指向的数据类型*指针的名字)例如:int

swap(int*pfirst,int*pSecond)调用方式:intm=5,n=6;intresult=0;int*pA,*pB;pA=&m;pB=&n;result=swap(pA,pB);26调用过程的数据传递:第一步560¥%#mnpApBresult@#4第二步560&mmnpApBresult&n第三步xresultpApB&m&n赋值操作函数内部处理return(x)pFirstpSecond&m&n27另一种说明方式28指针变量作为函数参数发生的效果1、其过程是通过实参给形参赋值2、实际效果是将实参的地址传递给了形式

参数3、因此在函数内部对输入数据的任何操作

都会影响到原始输入的数据。下面看一个例子:注意指针作函数参数的写法注意本例使用的函数调用方法29voidswap(int*p1,int*p2);voidmain(){

intx1=100,x2=200;printf("x1=%d,x2=%d\n",x1,x2);swap(&x1,&x2);printf("x1=%d,x2=%d\n",x1,x2);}voidswap(int*p1,int*p2){

inttemp;temp=*p1;*p1=*p2;*p2=temp;}

用指针变量编写实现两个数的交换的函数1.参数的传递过程2.其它的实现方法(如何正确使用)30swap函数的错误写法:voidswap(int*p1,int*p2){

int*ptemp;

ptemp=p1;p1=p2;p2=ptemp;}

31例7.3输入3个整数a,b,c,按由大到小顺

序输出。使用函数voidexchange(int*p1,int*p2,int*p3)说明:1.指针做函数的参数2.函数的嵌套调用327.2指针的运算指针的赋值运算赋值(类型必须匹配)变量地址;数组名;数组元素;其它指针;空指针(说明)不能直接给指针变量赋一个整数,如:p=0x1fff;加减运算(+、-)1.指针的±运算2.指针±整数自加自减运算(++、--、+=、-=)33指针的+、-运算说明:指针与整型值加减的结果是指针,表示使该指针指向该指针下移或上移存储单元个数(整型值)之后的内存地址。存储单元的大小就是该指针所指向变量的数据类型所需的内存大小。例如:ptr+n(指针ptr,n为整数)这个指针值代表的内存单元的地址是:ptr+n*d(其中d是指针所指向变量的数据类型所占内存字节数),即指针移动了n个元素。34⑵指针与指针的加运算毫无意义,所以指针与指针

没有加运算。⑶指针与指针的减运算要求相减的两个指针属于同一类型,其结果是整数,表示两个指针之间的数据的个数。其结果值的计算公式是:

ptr1-ptr2=(ptr1的值-ptr2的值)/指针的数据类型所占的字节数例如:

int*ptr1,*ptr2,*ptr3,x;

intary[5]={2,4,8,16,32};ptr1=&ary[0];ptr2=&ary[3];

ptr3=ary;x=ptr2-ptr1;

x的值是3352.指针的++、--、+=、-=运算++、+=:是移动指针到下一个或下几个存储单元。

--、-=:是移动指针到上一个或上几个存储单元。

例如:int*ptr,ary[5]={2,4,6,8,10};

ptr=ary;ptr+=3;ptr--;想一想:*ptr++和(*ptr)++有什么区别?36指针的关系运算 只有在两个指针变量指向同一数组中元素的情况下才能用关系运算符进行比较。P144-例7.4377.3指针与数组数组中每一个元素都有对应的地址,因此可以通过指针访问数组:第一种:直接访问数组元素第二种:通过指针引用数组元素inta[10]={0};int*pA,*pB;pA=&a[3];pB=&a[0];inta[10]={0};

int*pA,nTemp;

pA=&a[3];

nTemp=*(pA+1);38说明1:对于数组名,在C语言中规定数组名代表数组的首元素的地址。也就是说可以把数组名当作一个地址来看待。因此可将数组名赋值给一个指针,并通过指针的移动来访问数组中的每个元素。inta[10]={0};int*pA,nTemp;pA=a;nTemp=*(pA+1);inta[10]={0};int*pA,nTemp;pA=&a[0];nTemp=*(pA+1);39说明2:由于数组名是地址,因此也可以使用引用(取内容)操作符“*”来进行数组元素的访问。如:inta[10]={0};int*pA,nTemp;pA=a;nTemp=*(pA+1);inta[10]={0};int*pA,nTemp;nTemp=*(a+1);401.用下标法引用数组元素如:a[3]=45;b[2][5]=200;p[1]=1002.用指针法引用数组元素(两种)假如:inta[10],*p,i;p=a;则:⑴*(p+i)、*(a+i)都可以访问元素a[i]

*(p+i)、*(a+i)、a[i]、p[i]对数组变量的引用方法等价,都代表数组a的第i+1个元素(1)对数组元素的引用方法41例7.5:输出10个元素数组中的全部元素。方法二:通过数组名计算数组元素地址,找出元素的值。

int

main(){

inta[10]={54,65,8,2,3,56,8,21,57,98},i;

for(i=0;i<10;i++)printf("%4d",*(a+i));}方法一:下标法。

int

main(){

inta[10]={54,65,8,2,3,56,8,21,57,98},i;

for(i=0;i<10;i++)printf("%4d",a[i]);}42方法三:用指针变量指向数组元素

int

main(){

inta[10]={54,65,8,2,3,56,8,21,57,98},*p,i;p=a;

for(i=0;i<10;i++)printf("%4d",*p++);}以上三种方法,利用指针变量效率最高。

说明:⑴指针变量与数组名的区别:

指针变量是地址变量,数组名是地址常量。即指针变量的内容可以在程序运行过程中被改变;而数组名一旦被定义,它的值就不能被改变了。

例如:inti,*p,a[6];则:p=&i;√a=&i;a++;a+=i;不能给常量赋值43⑵利用指针变量编程时特别要注意指针变量的当前值。例7.6:通过指针变量输入输出a数组元素。main(){int*p,i,a[5];p=a;

for(i=0;i<5;i++)scanf("%d",p++);

for(i=0;i<5;i++)printf(“%6d”,*p++);}应插入语句p=a;44在使用指针变量指向数组元素时,应切实保证指向数组中有效的元素,如a[10]在编译时并不出错,而按*(a+10)处理,但得不到预期的结果*p++和*++p的不同*p++和(*p)++的不同45数组名作函数的参数例如:

f(int

arr[],intn){……}main(){intarray[10];……f(array,10);……}解释:实际上,C编译系统都是将形参数组名作为指针变量来处理的。上例中f(int

arr[],intn)等价于f(int*arr,intn)

。使用形参数组的概念只是为了与实参数组对应、直观、便于理解而已。46例:从10个数中找出其中最大值和最小值。voidmax_min(int

a[],int

n,int*max,int*min);intmain(){

int

i,a[]={2,4,1,6,7,32,45,75,45,90},max,min;

printf("Theoriginalarray=");

for(i=0;i<10;i++)printf("%5d",a[i]);max_min(a,10,&max,&min);

printf("max=%dmin=%d",max,min);}voidmax_min(inta[],intn,int*max,int*min){

inti;*max=*min=a[0];

for(i=0;i<n;i++){if(*max<a[i])*max=a[i];if(*min>a[i])*min=a[i];}}47上例中如果形参数组用指针变量,则程序如下:voidmax_min(int*x,int

n,int*max,int*min);main(){

inti,a[10]={2,4,1,6,7,32,45,75,45,90},max,min;

printf("Theoriginalarray=");

for(i=0;i<10;i++)printf("%5d",a[i]);max_min(a,10,&max,&min);

printf(“max=%dmin=%d",max,min);}voidmax_min(int*x,intn,int*max,int*min){

inti;*max=*min=*x;

for(i=1;i<n;i++,x++){if(*max<*x)*max=*x;if(*min>*x)*min=*x;}}48数组名做函数参数小结:如果有一个实参数组,想在函数中改变此数组的元素的值,实参与形参都可用数组名或指针变量其对应关系有以下4种情况:(P177-178)⑴实参与形参都用数组名;⑵实参用数组名、形参用指针变量;⑶实参、形参都用指针变量;⑷实参为指针变量、形参用数组名。49例:实参、形参都用指针变量的形式main(){inta[10],*p;p=a;……f(p,10);……}f(int*x,intn){……

}例:实参为指针变量,形参用数组名。main(){inta[10],*p;p=a;……f(p,10);……}f(intx[],intn){……

}50使用指针时候的重要说明注意:用指针变量作实参时一定要有确定的值。f(intx[],intn){……}main(){inta[10],*p;……

f(p,10);}main(){int*p,i;for(i=0;i<10;i++)scanf(“%d”,p++);

}51练习:选择法从大到小排序/**/main(){

int*p,i,a[10];

p=a;

for(i=0;i<10;i++)scanf(“%d”,p++);

p=a; sort(p,10);

for(p=a,i=0;i<10;i++){printf(“%d

”,*p);p++;}

printf(“\n”);}为什么52两类写法sort(intx[],intn){

int

i,j,k,t;

for(i=0;i<n-1;i++){ k=i;

for(j=i+1;j<n;j++) {

if(x[j]>x[k])k=j; }

if(k!=i) {t=x[i];

x[i]=x[k];

x[k]=t; }}}sort(int*x,intn){

int

i,j,k,t;

for(i=0;i<n-1;i++){ k=i;

for(j=i+1;j<n;j++) { if(*(x+j)>*(x+k))k=j; }

if(k!=i) {t=*(x+i); *(x+i)=*(x+k); *(x+k)=t; }}}537.3.2指针与字符串字符串/字符数组回顾:定义:charstr[10];初始化:charstr[]=“helloworld”charstr[]={‘h’,’e’,’l’,’l’,’o’}输出:printf(“%s”,str);printf(“%c”,str[1]);

puts(str);输入:gets(str);scanf(“%s”,str)scanf(“%s%s%s”,str1,str2,str3)54用指针处理字符串定义:char*pstr;初始化:char*pStr=“helloworld”;char*pStr;pStr=“helloworld”;输出:printf(“%s”,pStr);printf(“%c”,*(pStr+i));输入:一般需要借助数组来完成55字符指针变量和字符数组的异同概念字符数组由若干个元素组成,每个元素中放一个字符。而字符指针变量中存放的是地址(字符串的首地址)(仅仅占一个指针变量所占用的空间大小),而不是将整个字符串都放到字符指针变量中。56字符指针变量和字符数组的异同初始化:字符数组和字符指针变量都可以在定义时赋初值但以下方法对字符数组非法,对字符指针变量合法

chars[10];s=“hello!”;╳

char*ps;ps=“hello!”;√57字符指针变量和字符数组的异同字符数组名是指针常量,只能表示一个确定的字符串,不能改变。不能进行++,--等运算来改变其位置,而字符指针变量的值是可以改变的,它可以代表不同的字符串。若定义了一个指针变量,并使它指向一个字符串,就可以用下标形式引用指针变量所指向字符串中的字符。如:char*a=“IloveChina!”;printf(“%c”,a[5]);

58字符指针变量和字符数组的异同字符指针变量定义后,必须先被赋值后使用,而定义一个字符数组后即可马上使用例:charst[10];scanf(“%s”,st);char*s;scanf(“%s”,s);(错)应改为:

chara[20],*s;

s=a;(注意:这步必不可少)

scanf(“%s”,s);59例:将字符串a复制给字符串b。intmain(){chara[]=“Iamaboy",b[20];

inti=0;do{*(b+i)=*(a+i);i++;}while(*(a+i)!=‘\0’);/*也可写成while(*(a+i));*/

*(b+i)=‘\0’;

puts(b);}60上例程序还可写成:intmain(){

chara[]=“Iamaboy",b[20],*p1=a,*p2=b;

inti=0;do{

*p2=*p1;p2++;p1++;}while(*p1!='\0');/*也可写成while(*p1);*/

*p2=‘\0’;

puts(b);}61字符串指针作函数的参数同指针作函数参数一样,可以在子函数中改变字符数值,并在主函数中得到相应的变化内容。例:用函数调用实现字符串的复制62main(){ chara[]=“Iamateacher.”; charb[]=“Youareastudent.”;

printf(“stringa=%s\nstringb=%s\n”,a,b);

copy_string(a,b);

printf(“stringa=%s\nstringb=%s\n”,a,b);}用字符数组作参数voidcopy_string(char

from[],charto[]){

inti=0;

while(from[i]!=‘\0’){to[i]=from[i];i++;}

to[i]=‘\0’;}使用指针的方式voidcopy_string(char*from,char*to){ for(;*from!=‘\0’;from++,to++)*to=*from; *to=‘\0’;}使用指针的方式voidcopy_string(char*from,char*to){ while(*to++=*from++);}637.3.3指针和二维数组多维数组的回顾:定义:inta[3][4];访问其中的一个元素:a[2][1];如何访问第二行元素:a[1]存储方式:图为什么可以使用a[1]来访问第二行元素?C语言中多维数组的概念模型64多维数组概念模型以二维数组为例:在C语言中,一个二维数组可以看成是一个一维数组,其中每个元素又是一个包含若干元素的一维数组。(图)

假如有定义:inta[2][3];则C语言编译程序认为a数组是由a[0],a[1]两个元素组成的一维数组,a[0]和a[1]分别是包含三个元素的一维数组名,分别代表a数组元素的起始地址(即a[0]是第0行元素的首地址,a[1]是第1行元素的首地址)。a和a[0]是两个基类型不同的指针常量(再次说明)。65指针操作多维数组的基本知识数组名字的含义和操作设有一个二维数组;假设数组地址从2000开始inta[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}}考虑a,a[0],a[1][2]的意义考虑a+1,a[0]+1,a[1][2]+1的含义考虑*(a+1),*(a[0]+1),*(a[1][2]+1)考虑&(a+1),&(a[0]+1),&(a[1][2]+1)…66a[1][2]和a的意义a[1][2]是元素的地址a代表二维数组首元素的地址,首元素不是一个整型变量,而是由4个整型元素所组成的一维数组,因此a代表的是首行的首地址*a代表0行0列的地址即&a[0][0]如果首行首地址是2000,则a+1是多少?a+2是多少?

a+1的地址:2008;a+2的地址:2016a[1][2]是元素的内容67a[i]是一维数组名,是一个地址,它以数组的第一个元素的地址,作为地址。a[0]代表一维数组a[0]中第0列元素的地址,即&a[0][0],值为2000a[1]代表&a[1][0],值为2008a[i]的意义68a+i是指向行的指针,a[i]+j是指向列的指针a[1]和*(a+1)等价&a[0]与a等价*和&操作符69数组a的性质表示形式含义值a二维数组名,指向一维数组a[0],即第0行首地址2000a[0],*(a+0),*a第0行第0列元素的地址2000a+1,&a[1]第1行首地址2008a[1],*(a+1)第1行第0列元素a[1][0]的地址2008a[1]+2,*(a+1)+2,&a[1][2]第1行第2列元素a[1][2]的地址2012*(a[1]+2),*(*(a+1)+2),a[1][2]第1行第2列元素a[1][2]的值1370为什么a+1和*(a+1)都是2008呢?

a+1是a中第1行的首地址,而*(a+1)就是a[1],是指向a[1][0]的地址,二者值相同,但含义不同71&a[i]和a[i](元素地址)的值相同,但含义不同&a[i]或a+i指向行,即第i行a[i]或*(a+i)指向列,即第i行第0个元素72/*例*/#defineFORMAT“%d,%d\n”intmain(){

inta[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};

printf(FORMAT,a,*a); printf(FORMAT,a[0],*(a+0)); printf(FORMAT,&a[0],&a[0][0]); printf(FORMAT,a[1],a+1); printf(FORMAT,&a[1][0],*(a+1)+0); printf(FORMAT,a[2],*(a+2)); printf(FORMAT,&a[2],a+2); printf(FORMAT,a[1][0],*(*(a+1)+0));}73指向多维数组元素的指针变量指针可以用来指向二维甚至更高维的数组元素,但是需要注意高维数组的行、列定义。例如:

inta[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};

int*p;

是否可以写p=a;???分析:如果正确赋值必须左右两端的数据类型需要一致,a指向的元素是一维数组,而p指向的元素是int,因此这里不匹配可以使用的赋值方式:P=a[0]P=*(a+0)P=*aP=&a[0][0]74用指针变量输出二维数组元素的值main(){

inta[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};

int*p;

for(p=a[0];p<a[0]+12;p++) { if((p-a[0])%4==0)printf(“\n”); printf(“%4d”,*p); }}75指向数组的指针(二)特点:其指向的数据类型是数组,而不是简单的数据类型定义:数据类型(*指针名称)[数组尺寸]例如:int(*p)[4]含义:本身是一个指针变量,其指向的数据类型是包含4个元素的数组,这个数组中的元素是int型的。是否可以进行p=a;…其它方式76继续上一题main(){

inta[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};

int

(*p)[4]=a; for(…?) { printf(“%4d”,???); }}77用指向数组的指针作函数参数将多维数组向一个函数中进行传递的时候,可以采用的方法有多维数组名作参数使用指向元素的指针进行数据传递funName(int*p,int

col,introw)使用指向数组的指针进行数据传递funName(int(*p)[4],introw)例子:7.12有一个班,3个学生,各学4门课,计算总平均分数,以及第n个学生的成绩78main(){ voidaverage(float*p,intn); voidsearch(float(*p)[4],intn); floatscore[3][4]={{65,67,70,60},{80,87,90,81},{90,99,100,98}}; average(*score,12); search(score,2);}voidaverage(float*p,intn){ float*p_end; floatsum=0,aver;

p_end=p+n-1;

for(;p<=p_end;p++) sum=sum+(*p); aver=sum/n;

printf(“average=%5.2f\n”,aver);}voidsearch(float(*p)[4],intn){

inti;

printf(“thescoreofNo.%dare:\n”,n);

for(i=0;i<4;i++) printf(“%5.2f”,*(*(p+n)+i));}79例:在上例的基础上,查找一门以上课程不及格的学生,打印出他们的全部课程的成绩voidsearch(float(*p)[4],intn){

int

i,j,flag;

for(j=0;j<n;j++){ flag=0;

for(i=0;i<4;i++) if(*(*(p+j)+i)<60)flag=1;

if(flag==1){

printf(“No.%dfails,hisscoresare:\n”,j);

for(i=0;i<4;i++)printf(“%5.2f”,*(*(p+j)+i));

printf(“\n”);}}}80小结:指针存取数组元素的优点通过指针变量存取数组元素速度快。用指针变量作函数的形式参数,所处理的数组大小可以变化(特别是在处理多维数组的情况下),因此书写的程序很灵活。817.4函数的指针和指向函数的指针变量函数在运行的时候被分配给一个地址。程序在运行的时候,所有的调用函数过程都是从这个地址开始运行的。这个地址被就称为函数的入口地址(指针)。因此可以使用指针变量指向这个函数的入口地址。并通过这个指针变量来调用此函数。82指向函数的指针变量定义指向函数的指针的一般形式:类型标识符(*指针变量名)(形式参数类型列表)例如:int

(*p)(int,int);含意:p是一个指向函数的指针,这个函数中有两个参数其类型都是int型的,同时这个函数的返回值是一个int型的如何使用83#include<stdio.h>void

main(){intmax(int,int);

int

a,b,c;

scanf(″%d,%d″,&a,&b);c=max(a,b);

printf(″a=%d,b=%d,max=%d

″,a,b,c);}

intmax(int

x,int

y){int

z;

if(x>y)z=x;

elsez=y;

return(z);}求a、b的较大值84#include<stdio.h>void

main(){int

max(inta,intb);

int(*p)(int,int);/*定义*/

int

a,b,c;

p=max;/*赋值只给函数名不给参数*/

scanf(″%d,%d″,&a,&b);

c=(*p)(a,b);/*使用*/

printf(″a=%d,b=%d,max=%d″,a,b,c);}使用函数指针85说明:注意:不能写成p=max(a,b);pmaxp=max;/*赋值*/使用方式:c=(*p)(a,b)86用指向函数的指针作函数参数函数指针变量常用的用途之一是把指针作为参数传递到其他函数。指向函数的指针也可以作为参数,以实现函数地址的传递,这样就能够在被调用的函数中使用实参函数。使用函数做参数增加了函数的灵活性。这一种使用方法在现代程序设计中得到了非常广泛的应用,c++语言的多种概念的实现就是以这种方式来完成的(例如:多态)87实参函数名f1

f2↓↓voidsub(int(*x1)(int),int(*x2)(int,int))/*定义头*/{int

a,b,i,j;a=(*x1)(i);/*调用f1函数*/b=(*x2)(i,j);/*调用f2函数*/

}原理简述:88设一个函数process,在调用它的时候,每次实现不同的功能。输入a和b两个数,第一次调用process时找出a和b中大者,第二次找出其中小者,第三次求a与b之和。#include<stdio.h>voidmain(){intmax(int,int);/*函数声明*/

intmin(int,int);/*函数声明*/

intadd(int,int);/*函数声明*/voidprocess(int,int,int(*fun)(int,int));/*函数声明*/

int

a,b;

printf(″enteraandb:″);

scanf(″%d,%d″,&a,&b);89intmax(int

x,int

y)/*函数定义*/{int

z;

if(x>y)z=x;

elsez=y;

return(z);}intmin(int

x,int

y)/*函数定义*/

{int

z;

if(x<y)z=x;

elsez=y;

return(z);}

函数90

printf(″max=″);

process(a,b,max);

printf(″min=″);

process(a,b,min);

printf(″sum=″);

process(a,b,add);}使用方法91intadd(int

x,int

y)/*函数定义*/{intz;z=x+y;

return(z);}voidprocess(int

x,int

y,int(*fun)(int,int)){intresult;

result=(*fun)(x,y);

printf(″%d\n″,result);}函数的指针做参数的实现方式927.5指针型函数一个函数可以带回一个整型值、字符值、实型值等,也可以带回指针型的数据,即地址。其概念与以前类似,只是带回的值的类型是指针类型而已。这种带回指针值的函数,一般定义形式为类型名*函数名(参数表列);例如:int*a(int

x,int

y);含义:名称为a的函数中有两个参数x,y返回一个指向int类型的指针。93例有若干个学生的成绩(每个学生有4门课程),要求在用户输入学生序号以后,能输出该学生的全部成绩。用返回指针的函数来实现。

#include<stdio.h>voidmain(){floatscore[][4]={{60,70,80,90},

{56,89,67,88},{34,78,90,66}};float*search(float(*pointer)[4],intn);

float*p;

int

i,m;

printf(″enterthenumberofstudent:″);

scanf(″%d″,&m);

printf(″ThescoresofNo.%dare:\n″,m);

94

p=search(score,m);

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

printf(″%5.2f\t″,*(p+i));}float*search(float(*point)[4],int

n){float*pt;

pt=*(point+n);/*pt=point?*/return(pt);}

运行情况如下:enterthenumberofstudent:1↙ThescoresofNo.1are:56.0089.0067.0088.00957.6指针数组和指向指针的指针7.6.1指针数组的概念一个数组,若其元素均为指针类型数据,称为指针数组,也就是说,指针数组中的每一个元素都相当于一个指针变量。一维指针数组的定义为:类型名*数组名[数组长度];例如:int*p[4];应用:指针数组通常用来处理字符串问题96指针数组在处理字符串方面的一些特点1、精简的内存分配空间图示2、快速的数据操作能力不必对数组中的每一个元素进行操作例题:

将若干字符串按字母顺序(由小到大)输出。9798#include<stdio.h>#include<string.h>voidmain(){

char*name[]={“Followme”,“BASIC”,“GreatWall″,”FORTRAN“,”Computerdesign“};/*初始化方式*/

int

n=5;

sort(name,n);

print(name,n);}99voidsort(char*name[],int

n){char*temp;

int

i,j,k;

for(i=0;i<n-1;i++){k=i;

for(j=i+1;j<n;j++)

if(strcmp(name[k],name[j])>0)k=j;

if(k!=i) {

temp=name[i];name[i]=name[k];name[k]=temp;}}}

选择排序(指针数组做函数参数)如何使用100voidprint(char*name[],int

n){int

i;

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

printf(″%s\n″,name[i]);

}还可以如何写*(name++)Name[0]Name[1]Name[2]Name[3]Name[4]FollowmeBASICGreatWallFORTRANComputerdesign101指向指针的指针定义:指向指针数据的指针变量格式数据类型**指针名称;例如:char**pCh;说明:本身仍然是一个指针,特点在于指向的数据类型用来灵活操作指针数组102例:使用指向指针的指针。

#include<stdio.h>voidmain(){char*name[]={"Followme","BASIC","GreatWall″,"FORTRAN","Computerdesign"};char**p;/*通常不用其进行初始化*/

int

i;

for(i=0;i<5;i++){p=name+i;/*赋值方式*/

printf(″%s\n″,*p);/*使用方式*/

}}103#include<stdio.h>voidmain(){int

a[5]={1,3,5,7,9};

int*num[5]={&a[0],&a[1],/*为什么这么写*/&a[2],&a[3],&a[4]};

int**p,i;p=num;

for(i=0;i<5;i++){printf(″%d″,**p);/*写成*p会如何?*/

p++;}}例

一个指针数组的元素指向整型数据的简单例子104指针数组可以作main函数的形参指针数组也可以作函数的参数在做main函数的参数的时候,通过命令行参数来进行函数的调用。例如:voidmain(int

argc,charargv[])命令行的一般形式为命令名参数1参数2……参数n105例如一个名为file1的文件,它包含以下的main函数:voidmain(int

argc,char*argv[]){while(argc>1){++argv;

printf(″%s\n″,*argv);--argc;}}在DOS命令状态下输入的命令行为file1ChinaBeijing则执行以上命令行将会输出以下信息:ChinaBeijing106有关指针的数据类型和指针运算的小结指针指向的各种数据类型指针同数组的联系与区别指针可以进行的运算回顾使用指针的注意事项107定义含义inti;定义整型变量iint*p;p为指向整型数据的指针变量inta[n];定义整型数组a,它有n个元素int*p[n];定义指针数组p,它由n个指向整型数据的指针元素组成int(*p)[n];p为指向含n个元素的一维数组的指针变量intf();f为带回整型函数值的函数int*p();p为带回一个指针的函数,该指针指向整型数据int(*p)();p为指向函数的指针,该函数返回一个整型值int**p;p是一个指针变量,它指向一个指向整型数据的指针变量指针指向的各种数据类型108int**(*p)(int(*p1)[4],int*p1[4])109指针和数组的联系与区别指针在操作上完全可以同数组的操作等价,但是数组的操作不能同指针等价。例如:char*p的初始化关键的原因在于数组分配数据的内存,而指针不进行分配。110指针可以进行的运算回顾(1)指针变量加(减)一个整数例如:p++、p--、p+i、p-i、p+=i、p-=i等。(2)赋值(将一个变量地址赋给一个指针变量)p=&a;(将变量a的地址赋给p)p=array;(将数组array首元素地址赋给p)p=&array[i];(将数组array第i个元素的地址赋给p)p=max;(max为已定义的函数,将max的入口地址赋给p)p1=p2;(p1和p2都是指针变量,将p2的值赋给p1)111赋值NULL(3)指针进行减法运算前提是指针指向的内容一致(数组中的元素)(4)指针进行比较前提是指针指向同一数组中的元素(5)指针的转换void类型,强制转换的方法112使用指针的注意指针很灵活,因此使用的时候要注意:指针要进行初始化,不能让其悬空。指针是地址的代名词,因此其中只能装入地址即使是地址,也要注意指针指向的数据类型是否一致。注意*和&两个特殊的运算符注意*在多维数组中的用途A[i]同*(a+i)的关系要牢记113习题输入3个数,按从小到大顺序输出swap(int

x,inty){inttemp;temp=x;x=y;y=te

温馨提示

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

评论

0/150

提交评论