全国二级等级考试2012-9辅导多媒体课件第9讲_第1页
全国二级等级考试2012-9辅导多媒体课件第9讲_第2页
全国二级等级考试2012-9辅导多媒体课件第9讲_第3页
全国二级等级考试2012-9辅导多媒体课件第9讲_第4页
全国二级等级考试2012-9辅导多媒体课件第9讲_第5页
已阅读5页,还剩66页未读 继续免费阅读

下载本文档

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

文档简介

第9讲指针指针是C语言中的重要概念,也是C语言的重要特色。使用指针,可以使程序更加简洁、紧凑、高效。9.1指针和指针变量的概念9.2指针变量的定义与应用9.3数组的指针和指向数组的指针变量

9.4字符串的指针和指向字符串的指针变量9.5返回指针值的函数

9.6指针数组与主函数main()的形参

9.7函数的指针和指向函数的指针变量9.1指针和指针变量的概念1.内存地址──内存中存储单元的编号1)计算机硬件系统的内存储器中,拥有大量的存储单元(容量为1字节)。为了方便管理,必须为每一个存储单元编号,这个编号就是存储单元的“地址”。每个存储单元都有一个惟一的地址。2)在地址所标识的存储单元中存放数据。注意:内存单元的地址与内存单元中的数据是两个完全不同的概念。例:inta;a=12;变量a内的“内容”(变量值)是12;变量值可由键盘等方法录入a变量的地址&a,是3000,变量的地址&a是编译时系统统一编码赋予的。123000a图9-12.变量地址──系统分配给变量的内存单元的起始地址假设有这样一个程序:

main(){intnum;scanf("%d",&num);printf("num=%d\n",num);}C编译程序编译到该变量定义语句时,将变量num登录到“符号表”中。符号表的关键属性有两个:一是“标识符名(id)”,二是该标识符在内存空间中的“地址(addr)”。为描述方便,假设系统分配给变量num的4字节存储单元为3000至3003,则起始地址3000就是变量num在内存中的地址。

3.变量值的存取──通过变量在内存中的地址进行系统执行“scanf(”%d“,&num);”和“printf(”num=%d\n“,num);”时,存取变量num值的方式可以有两种:(1)直接访问──直接利用变量的地址进行存取

1)上例中scanf(“%d”,&num)的执行过程是这样的:用变量名num作为索引值,检索符号表,找到变量num的起始地址3000;然后将键盘输入的值(假设为12)送到内存单元3000至3003中。此时,变量num在内存中的地址和值,如图9-1所示。

2)printf("num=%d\n",num)的执行过程,与scanf()很相似:首先找到变量num的起始地址3000,然后从3000至3003中取出其值,最后将它输出。(2)间接访问──通过另一变量访问该变量的值C语言规定:在程序中可以定义一种特殊的变量(称为指针变量),用来存放其它变量的地址。例如,假设定义了这样一个指针变量p,它被分配到4000至4003单元,其值可通过赋值语句“p=#”得到。此时,指针变量p的值就是变量num在内存中的起始地址3000,如图9-2所示(见下一页)。通过指针变量p存取变量num值的过程如下:首先找到指针变量p的地址(4000),取出其值3000(正好是变量num的起始地址);然后从3000至3003中取出变量num的值(3)。(3)两种访问方式的比较两种访问方式之间的关系,可以用某人甲(系统)要找某人乙(变量)来类比。一种情况是,甲知道乙在何处,直接去找乙就是(即直接访问)。另一种情况是,甲不知道乙在哪,但丙(指针变量)知道,此时甲可以这么做:先找丙,从丙处获得乙的地址,然后再找乙(即间接访问)。main(){intnum=12;int*p;/*p是专门用于存放其他变量(num)地址的变量,(存放整型变量地址)*/p=#/*p是变量,专门存放整形变量地址(这里不要写成“*p”)*/scanf(“%d”,p);scanf(“%d”,&num);printf(“%d\n”,*p);printf(“%d\n”,num);}运行结果:12(对应scanf(“%d”,p);)12(scanf(“%d”,&num);)12(printf(“%d\n”,num);)12(printf(“%d\n”,*p);)p=#num的首地址是3000,将num地址装入了指针变量p40004003300012pnum30003003图9-2p=#num的首地址是3000p指向了(首地址为3000)变量num4.指针与指针变量(1)指针──即地址(指针变量的值,称为指针,这个值是其他变量的地址)

一个变量的地址称为该变量的指针。通过变量的指针能够找到该变量。(2)指针变量──专门用于存储其它变量地址的变量指针变量p的值就是变量num的地址。指针与指针变量的区别/关系,就是变量值与变量(名)的区别/关系。(3)为表示指针变量和它指向的变量之间的关系,用指针运算符“*”表示。例如,指针变量p与它所指向的变量num的关系,(在上例中)表示为:*p,即*p等价于变量num。而p等价于变量&num因此,下面两个语句(num=3;*p=3;)的作用相同:int*p,num;/*定义p为指针变量,定义num为指普通变量*//*int表示p指向整型变量,“*”表示p是指针型变量*/num=3; /*将3直接赋给普通变量num*/p=#/*把num的地址装入p,使p指向num*/*p=3; /*将3赋给指针变量p所指向的变量*/[Return]指针变量的概念与小结

:指针:变量a的地址,称为变量a的指针;即&a称为变量a的指针指针变量:用于专门存放地址的变量称为指针变量(p)。指针变量定义的格式:

基类型

*指针变量;普通变量定义:inta;指针变量定义:int*p;1.对指针变量,定义语句中各符号的说明类型符号“*”:说明p

是指针变量基类型符号int:说明p存储整型变量的地址。(基类型,用于指针运算时的步长单位,稍后可见)

变量名:p(不要用“*P”作变量名,符号“*”只是类型说明)。2.对指针变量,引用语句中各符号的说明常用运算符号:

&:取址运算,如:&a,取变量a地址

*

:取值运算(指针运算),取指针变量指向的变量的数值例:inta=2,*p;/*定义*/p=&a;scanf(“%d”,p);printf(“%d”,*p))/*引用*/3.对于指针变量的符号“*”,出现在不同位置,其作用不同(1)定义中:“*”说明所定义的变量是指针变量(2)引用中:“*”是指针运算符,取指针变量指向的变量的数值

9.2指针变量的定义与应用

9.2.1指针变量的定义与相关运算

[案例9.1]指针变量的定义与相关运算示例。

/*案例代码文件名:AL9_1.C*/

#include<stdio.h>main()

{intnum_int=12,*p_int; /*定义一个指向int型数据的指针变量p_int*/

floatnum_f=3.14,*p_f; /*定义一个指向float型数据的指针变量p_f*/

charnum_ch=’p’,*p_ch; /*定义一个指向char型数据的指针变量p_ch*/

p_int=&num_int; /*取变量num_int的地址,赋值给p_int*/

p_f=&num_f; /*取变量num_f的地址,赋值给p_f*/

p_ch=&num_ch; /*取变量num_ch的地址,赋值给p_ch*/

printf(“num_int=%d,*p_int=%d\n”,num_int,*p_int);

printf(“num_f=%4.2f,*p_f=%4.2f\n”,num_f,*p_f);

printf(“num_ch=%c,*p_ch=%c\n”,num_ch,*p_ch);

} AL9_1.C

[程序演示]300012p_int*p_int30003003图9-2num_int40004003程序运行结果:num_int=12,*p_int=12num_f=3.14,*p_f=3.14num_ch=p,*p_ch=p

程序说明:(1)头三行的变量定义语句──指针变量的定义与一般变量的定义相比,除变量名前多了一个星号“*”(指针变量的定义标识符)外,其余一样:基(数据)类型

*指针变量[,*指针变量2……];

注意:此时的指针变量p_int、p_f、p_ch,并未指向某个具体的变量(称指针是悬空的)。使用悬空指针很容易破坏系统,导致系统瘫痪。(2)中间三行的赋值语句──取地址运算(&)取地址运算的格式:&变量例如,&num_int、&num_f、&num_ch的结果,分别为变量num_int、num_f、num_ch的地址。注意:指针变量只能存放指针(地址),且只能是相同类型变量的地址。例如,指针变量p_int、p_f、p_ch,只能分别接收int型、float型、char型变量的地址,否则出错。(3)后三行的输出语句──指针运算(*)使用直接访问和间接访问两种方式,分别输出变量num_int、num_f、num_ch的值。注意:这三行出现在指针变量前的星号“*”是指针运算符,访问指针变量所指向的变量的值,而非指针定义标识符。理解:如果已定义point1是指向变量a的指针变量,

(inta=12,*point1;point1=&a;)

则1、&*point1的含义:&a,即变量a的地址;2、*&a的含义:即变量a;3、(*point1)++:即a++*point1++:等价*(point1++)

[案例9.2]使用指针变量求解:输入2个整数,按升序(从小到大排序)输出。/*案例代码文件名:AL9_2.C*/main(){intnum1,num2;int*num1_p=&num1,*num2_p=&num2,*pointer;printf(“Inputthefirstnumber:”);scanf(“%d”,num1_p);printf(“Inputthesecondnumber:”);scanf(“%d”,num2_p);printf(“num1=%d,num2=%d\n”,num1,num2);if(*num1_p>*num2_p)/*如果num1>num2,则交换指针*/{pointer=num1_p,num1_p=num2_p,num2_p=pointer;}printf(“min=%d,max=%d\n”,*num1_p,*num2_p);printf(“num1=%d,num2=%d\n”,num1,num2);}AL9_2.C[程序演示]num1_p&num2num2_p&num1num19num26交换指针后:num1_p&num1num2_p&num2num19num26交换指针前:程序运行情况:Inputthefirstnumber:9←┘Inputthesecondnumber:6←┘num1=9,num2=6min=6,max=9num1=9,num2=6程序说明:(1)第5行的if语句如果*num1_p>*num2_p(即num1>num2),则交换指针,使num1_p指向变量num2(较小值),num2_p指向变量num1(较大值)。(2)printf(“min=%d,max=%d\n”,*num1_p,*num2_p);语句:通过指针变量,间接访问变量的值。9.2.2指针变量作函数参数1.指针变量,既可以作为函数的形参,也可以作函数的实参。2.指针变量作实参时,与普通变量一样,也是“值传递”,即将指针变量的值(一个地址)传递给被调用函数的形参(必须是一个指针变量)。注意:被调用函数不能改变实参指针变量的值,但可以改变实参指针变量所指向的变量的值。[案例9.3]使用函数调用方式改写[案例9.2],要求实参为指针变量。/*案例代码文件名:AL9_3.C*/

/******************************************************/

/*exchange()功能:交换2个形参指针变量所指向的变量的值*/

/*形参:2个,均为指向整型数据的指针变量*/

/*返回值:无*/

/******************************************************/

voidexchange(int*pointer1,int*pointer2)

{inttemp;

temp=*pointer1,*pointer1=*pointer2,*pointer2=temp;

}/*主函数main()*/main(){intnum1,num2;int*num1_p=&num1,*num2_p=&num2;printf(“Inputthefirstnumber:”);scanf(“%d”,num1_p);printf(“Inputthesecondnumber:”);scanf(“%d”,num2_p);printf(“num1=%d,num2=%d\n”,num1,num2);if(*num1_p>*num2_p) /*即num1>num2)*/

exchange(num1_p,num2_p); /*指针变量作实参*/ /*输出排序后的num1和num2的值*/printf(“min=%d,max=%d\n”,num1,num2);} AL9_3.C[程序演示][案例9.3]与[案例9.2]的主要区别是

通过函数exchange()的调用,交换2个形参指针变量所指向的变量的值。功能:/*在函数exchange()的调用中,实参把地址传给形参,形参指针变量所指向的(变量)存储单元地址与实参指针变量所指向的(变量)存储单元地址是同一单元。其效果是:交换2个形参指针变量所指向的变量的值,实参指针变量所指向的变量的值也随之交换。原因是:实参、形参指向的是同一地址单元num2_p&num2pointer2&num2num26num1_p&num1pointer1&num1num

18函数的调用时,把实参指针变量的值(地址),传给了形参指针变量,形、实二者指向的是同一地址单元:num1_p&num1num2_p&num2num16num28变量的值交换后:num1_p&num1num2_p&num2num18num26变量的值交换前:-----------------------------图9-5----------------------------调用函数exchange()之前、之时、结束时和结束后的情况,如图所示(见前一页)。形参指针变量pointer1(指向变量num1)和pointer2(指向变量num2),在函数调用开始时才分配存储空间,函数调用结束后立即被释放。虽然被调用函数不能改变实参指针变量的值,但可以改变它们所指向的变量的值。9.3数组的指针和指向数组的指针变量9.3.1概述1.概念数组的指针──数组在内存中的起始地址,数组元素的指针──数组元素在内存中的起始地址。2.指向数组的指针变量的定义指向数组的指针变量的定义,与指向普通变量的指针变量的定义方法一样。例如,intarray[10],*pointer=array(或&array[0]);

或者:

intarray[10],*pointer;pointer=array;注意:数组名代表数组在内存中的起始地址(与第1个元素的地址相同),所以可以用数组名给指针变量赋值。3.数组元素的引用数组元素的引用,既可用下标法,也可用指针法。使用下标法,直观;而使用指针法,能使目标程序占用内存少、运行速度快。9.3.2通过指针引用数组元素如果有“inta[10],*p=a;”,则:(1)p+i和a+i都是数组元素a[i]的地址,如图9-6(见下一页)所示。实际地址为p+i*d,d为每个数组元素所占的字节数。(2)*(p+i)和*(a+i)就是数组元素a[i]。实际上,在编译时,对数组元素a[i]就是处理成*(a+i)。(3)指向数组的指针变量,也可将其看作是数组名,因而可按下标法来使用。例如,p[i]等价于*(p+i)。注意:p+1指向数组的下一个元素,而不是简单地使指针变量p的值+1。其实际变化为p+1*size(size为一个元素占用的字节数)。例如,假设指针变量p的当前值为1000,则p+1为1000+1*4=1004,而不是1001。如图9-6(见下一页)所示定义字节数d/步长假设:p指向地址为1000;i=1时基类型指针类型说明符变量名p+i表示的地址为:p+i╳dchar*p11001int2/41002/1004float41004元素起始地址a[0]

1000a[1]

1004a[2]

1008a[3]

1012a[i]

1016

a[5]

1020a[6]

1024a[7]

1028a[8]

1032a[9]

1036a

数组如果有“inta[10],*p=a;”,则:(1)p+i和a+i都是数组元素a[i]的地址,如图所示。实际地址为p+i*d,d为每个数组元素所占的字节数。(2)*(p+i)和*(a+i)就是数组元素a[i]。实际上,在编译时,对数组元素a[i]就是处理成*(a+i)。(3)指向数组的指针变量,也可将其看作是数组名,因而可按下标法来使用。例如,p[i]等价于*(p+i)。(有条件:p=a;)等价元素a[i]。

*(p+i)

*(p+9)

p1000p+1,a+1p+i,a+i&a[i]p+9,a+9&a[9]图9-6[案例9.5]使用指向数组的指针变量来引用数组元素。/*案例代码文件名:AL9_5.C*//*程序功能:使用指向数组的指针变量来引用数组元素*/#include<stdio.h>main(){intarray[10],*p=array,i;printf(“Input10numbers:”);

for(i=0;i<10;i++)scanf(“%d”,p+i); /*使用指针变量来输入数组元素的值*/printf(“array[10]:”);

for(i=0;i<10;i++)printf(“%d”,*(p+i)); /*使用指向数组的指针变量输出数组元素的值*/printf(“\n”);} AL9_5.C

[程序演示]程序运行情况:Input10numbers:0123456789←┘array[10]:0123456789

说明:(1)指针变量的值是可以改变的,所以必须注意其当前值,否则容易出错。(2)指向数组的指针变量,可以指向数组以后的内存单元,虽然没有实际意义。(3)对指向数组的指针变量(px和py)进行算术运算和关系运算的含义

1)可以进行的算术运算,只有以下几种:

px±n,px++/++px,px--/--px,px-py·px±n:将指针从当前位置向前(+n)或回退(-n)n个数据单位,而不是n个字节。显然,px++/++px和px--/--px是px±n的特例(n=1)。

·px-py:两指针变量的值之差,其意义是两指针之间的数据(数组元素的)个数,而不是指针的地址之差。思考题:若有以下定义和语句,且0≤i<10,则对数组元素的错误引用是:inta[]={1,2,3,4,5,6,7,8,9,10},

int*p=a,i;

A*(a+i)Ba[p-a]

Cp+iD*(&a[i])2)关系运算表示两个指针所指地址之间、位置的前后关系:前者为小,后者为大。例如,如果指针px所指地址在指针py所指地址之前,则px〈py的值为1。

9.3.3再论数组名作函数参数数组名作形参时,接收实参数组的起始地址;作实参时,将数组的起始地址传递给形参数组。引入指向数组的指针变量后,数组及指向数组的指针变量作函数参数时,可有4种等价形式(本质上是一种,即指针数据作函数参数):(1)形参、实参都用数组名(2)形参、实参都用指针变量(3)形参用指针变量、实参用数组名(4)形参用数组名、实参用指针变量2007年4月1、有以下程序

voidf(int*q)

{inti=0;

for(;i<5;i++)(*q)++;

}

main()

{inta[5]={1,2,3,4,5},i;

f(a);

for(i=0;i<5;i++)printf(“%d,”,a[i]);

}程序运行后的输出结果是()

A)2,2,3,4,5,

B)6,2,3,4,5,

C)1,2,3,4,5,

D)2,3,4,5,6,2007年4月2、以下程序的输出结果是_____________intfun(int*x,intn){if(n==0)returnx[0];elsereturnx[0]+fun(x+1,n-1);}main(){inta[]={1,2,3,4,5,6,7};printf(“%d\n”,fun(a,3));}102007年9月1、若在定义语句:int

a,b,c,*p=&c;之后,接着执行以下选项中的语句,则能正确执行的语句是A)scanf(“%d”,a,b,c);

B)scanf("%d%d%d",a,b,c);C)scanf(“%d”,p);

D)scanf("%d",&p);2007年9月2、有以下程序

#include<stdio.h>

void

fun(int*a,int

n)/*函数功能是将a所指数组元素从大到小排序*/

{int

t,i,j;

for(i=0;i<n-1;i++)for(j=i+1;j<n;j++)if(a[i]<a[j]){t=a[i];a[i]=a[j];a[j]=t;}}

main()

{int

c[10]={1,2,3,4,5,6,7,8,9,0},i;

fun(c+4,6);

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

printf("%d,",c[i]);

printf("\n");

}程序运行的结果是

A)1,2,3,4,5,6,7,8,9,0,

B)0,9,8,7,6,5,1,2,3,4,

C)0,9,8,7,6,5,4,3,2,1,

D)1,2,3,4,9,8,7,6,5,0,2007年9月3、有以下程序

#include<stdio.h>

void

fun(int

n,int*p)

{int

f1,f2;

if(n==1||n==2)*p=1;

else

{

fun(n-1,&f1);

fun(n-2,&f2);*p=f1+f2;

}

}

main()

{

int

s;

fun(3,&s);

printf("%d\n",s);

}程序的运行结果是

A)2

B)3

C)4

D)52008年4月1、以下定义语句中正确的是A)inta=b=0;

B)charA=65+1,b='b';C)floata=1,*b=&a,*c=&b;

D)doublea=0.0;b=1.1;2、有以下程序#include<stdio.h>main(){

inta[]={1,2,3,4},y,*p=&a[3];

--p;

y=*p;

printf("y=%d\n",y);}程序运行的结果是A)y=0

B)y=1

C)y=2

D)y=32008年4月3、有以下程序#include<stdio.h>voidfun(int*s,intn1,intn2){inti,j,t;i=n1;j=n2;while(i<j){t=s[i];s[i]=s[j];s[j]=t;i++;j--;}}main(){inta[10]={1,2,3,4,5,6,7,8,9,0},k;fun(a,0,3);fun(a,4,9);fun(a,0,9);for(k=0;k<10;k++)printf("%d",a[k]);printf("\n");}程序运行得结果是A)B)C)5678901234D)2008年4月4、以下程序的输出结果是【35】。

#include<stdio.h>

void

swap(int*a,int*b)

{

int*t;

t=a;a=b;b=t;

}

main()

{

inti=3,j=5,*p=&i,*q=&j;

swap(p,q);

printf("%d%d\n",*p,*q);

}2008年4月5、以下程序的输出结果是【4】。

#include

<stdio.h>

main()

{

int

a[5]={2,4,6,8,10},*p;

p=a;

p++;

printf("%d",*p);

}2008年9月1、若有定义语句:double

x[5]={1.0,2.0,3.0,4.0,5.0},*p=x;则错误引用x数组元素的是A)*p

B)x[5]

C)*(p+1)

D)*x2、以下程序的输出结果是【】

#include

<stdio.h>

main()

{

intj,a[]={1,3,5,7,9,11,13,15},*p=a+5;

for(j=3;j;j--)

{switch(j)

{case1:

case2:

printf("%d",*p++);

break;

case3:

printf("%d",*(--p));

}

}

}99112008年9月3、以下程序的输出结果是【】

#include

<stdio.h>

#define

N

5

int

fun(int*s,

int

a,

int

n)

{

int

j;*s=a;

j=n;

while(a!=s[j])

j--;

return

j;

}

main()

{

int

s[N+1];

int

k;

for(k=1;k<=N;k++)

s[k]=k+1;

printf("%d\n",fun(s,4,N));

}32009年3月1、若有定义语句:doublex,y,*px,*py;执行了px=&x;py=&y;之后,正确的输入语句是A)scanf(“%f%f”,x,y);

B)scanf("%f%f"&x,&y);C)scanf(“%lf%le”,px,py);

D)scanf(“%lf%lf”,x,y);2、有以下程序,程序执行后,输出结果是【】#include<stdio.h>void

fun(int*a){

a[0]=a[1];}main(){

int

a[10]={10,9,8,7,6,5,4,3,2,1},i;

for(i=2;i>=0;i--)

fun(&a[i]);

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

printf("%d",a[i]);

printf("\n");}77776543212009年3月3、有以下程序#include<stdio.h>voidfun(int*a,

int*b){int*c;

c=a;

a=b;

b=c;}main(){intx=3,y=5,*p=&x,*q=&y;fun(p,q);printf("%d,%d,",*p,*q);fun(&x,&y);printf("%d,%d\n",*p,*q);}程序运行后输出的结果是A)3,5,5,3

B)3,5,3,5

C)5,3,3,5

D)5,3,5,3

2009年3月4、有以下程序#include<stdio.h>voidf(int*p,

int*q);main(

){intm=1,

n=2,

*r=&m;

f(r,&n);printf("%d,%d",m,n);}voidf(int*p,

int*q){p=p+1;

*q=*q+1;}程序运行后的输出结果是A)1,3

B)2,3

C)1,4

D)1,22009年3月5、以下函数按每行8个输出数组中的数据#include<stdio.h>voidfun(int*w,

intn){

inti;for(i=0;i<n;i++){____________

printf("%d",w[i]);}printf("\n");}下划线出应填入的语句是A)if(i/8==0)printf(“\n”);

B)if(i/8==0)continue;C)if(i%8==0)printf("\n");D)if(i%8==0)continue;2009年3月6、若有以下定义intx[10],*pt=x;则对数组元素的正确引用是A)*&x[10]B)*(x+3)C)*(pt+10)D)pt+32009年3月7、有以下程序#include<stdio.h>intb=2;intfun(int*k){b=*k+b;

return

(b);}main(){inta[10]={1,2,3,4,5,6,7,8},

i;for(i=2;i<4;i++){b=fun(&a[i])+b;printf("%d",b);}printf("\n");}程序运行后的输出结果是A)1012B)810C)1028D)10162009年9月1、有以下程序#include<stdio.h>main(

){

intm=1,n=2,*p=&m,*q=&n,*r;r=p;p=q;q=r;printf("%d,%d,%d,%d\n",m,n,*p,*q);}程序运行后的输出结果是A)1,2,1,2B)1,2,2,1C)2,1,2,1D)2,1,1,22010年3月1、有以下程序#include<stdio.h>voidfun(char*c,

intd){*c=*c+1;d=d+1;printf("%c,%c,",*c,d);

}

main()

{charb='a',a='A';fun(&b,a);

printf(“%c,%c\n",b,a);

}程序运行后的输出结果是

A)b,B,b,AB)b,B,B,AC)a,B,B,aD)a,B,a,B2、设有定义doublea[10],*s=a;,以下能够代表数组元素a[3]的是A)(*s)[3]B)*(s+3)C)*s[3]D)*s+32010年3月3、有以下程序#include<stdio.h>#defineN8voidfun(int*x,

inti){*x=*(x+i);}main(){inta[N]={1,2,3,4,5,6,7,8},i;fun(a,2);for(i=0;i<N/2;i++){printf("%d",a[i]);}printf("\n");}程序运行后的输出结果是A)1313B)2234C)3234D)12342010年3月4、以下程序的功能是:借助指针变量找出数组元素中的最大值及其元素的下标值。请填空。#include<stdio.h>main(){inta[10],*p,*s;for(p=a;p-a<10;p++)scanf("%d",p);for(p=a,s=a;p-a<10;p++)if(*p>*s)s=【

】;printf("index=%d\n",s-a);}p2010年9月1、以下程序段完全正确的是A)int*p;scanf("%d",&p);B)int*p;scanf("%d",

p);C)intk,*p=&k;scanf("%d",p);D)intk,*p;*p=&k;scanf("%d",p);2、有以下程序

#include<stdio.h>voidf(int*p);main()

{inta[5]={1,2,3,4,5},*r=a;

f(r);printf("%d\n";*r);

}voidf(int*p)

{p=p+3;printf("%d,",*p);}程序运行后的输出结果是A)1,4B)4,4C)3,1D)4,12010年9月3、有以下程序(函数fun只对下标为偶数的元素进行操作)

voidfun(int*a;intn){inti,j,k,t;

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

for(j=i;j<n;j+=2)if(a[j]>a[k])k=j;

t=a[i];a[i]=a[k];a[k]=t;}}

main(){intaa[10]={1,2,3,4,5,6,7},i;fun(aa,7);

for(i=0;i<7;i++)printf("%d,",aa[i]));}程序运行后的输出结果是

A)7,2,5,4,3,6,1B)1,6,3,4,5,2,7C)7,6,5,4,3,2,1D)1,7,3,5,6;2,12010年9月4、有以下程序

#include<stdio.h>

int*f(int*p,int*q);

main()

{intm=1,n=2,*r=&m;

r=f(r,&n);printf("%d\n",*r);

}

int*f(int*p,int*q)

{return(*p>*q)?p:q;}程序运行后的输出结果是【】22010年9月5、以下程序的功能是:借助指针变量找出数组元素中最大值所在的位置并输出该最大值。请在输出语句中填写代表最大值的输出项。

#include<stdio.h>

main(){inta[10],*p,*s;

for(p=a;p-a<10;p++)scanf("%d",p);

for(p=a,s=a;p-a<10;p++)if(*p>*s)s=p;

printf("max=%d\n",【】);}*s2011年3月1、设有定义:doublex[10],*p=x;,以下能给数组x下标为6的元素读入数据的正确语句是A)scanf("%f",&x[6]);B)scanf("%lf",*(x+6));C)scanf("%lf",p+6);D)scanf("%lf",p[6]);答案C2011年9月1、若有定义语句:doublea,*p=&a;以下叙述中错误的是()。A)定义语句中的*号是一个间址运算符B)定义语句中的*号只是一个说明符C)定义语句中的p只能存放double类型变量的地址D)定义语句中,*p=&a把变量a的地址作为初值赋给指针变量p2、若有定义语句:intyear=2009,*p=&year;,以下不能使变量year中的值增至2010的语句是()。A)*p+=1;B)(*p)++;C)++(*p);D)*p++;答案A答案D2011年9月3、有以下程序voidfun(int*p){printf("%d\n",p[5]);}main(){inta[10]={1,2,3,4,5,6,7,8,9,10};fun(&a[3]);}程序运行后的输出结果是()。A)5B)6C)8D)94、以下程序的主函数中调用了在其前面定义的fun函数#include<stdio.h>…main(){doublea[15],k;k=fun(a);}则以下选项中错误的fun函数首部是()。A)doublefun(doublea[15])B)doublefun(double*a)C)doublefun(doublea[])D)doublefun(doublea)答案D答案D2011年9月5、以下程序调用fun函数把x中的值插入到a数组下标为k的数组元素中。主函数中,n存放a数组中数据的个数。请填空。

#include<stdio.h>voidfun(ints[],int*n,intk,intx){inti;

for(i=*n-1;i>=k;i--)s[【】]=s[i];

s[k]=x;*n=*n+【】;

}main(){inta[20]={1,2,3,4,5,6,7,8,9,10,11},i,x=0,k=6,n=11;

fun(a,&n,k,x);

for(i=0;i<n;i++)printf("%4d",a[i]);printf("\n");}i+119.3.42维数组的指针及其指针变量

1.2维数组的指针

假设有如下数组定义语句:

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

(1)从2维数组角度看,数组名a代表数组的起始地址,是一个以行为单位进行控制的行指针:

a+i:行指针值,指向2维数组的第i行。

*(a+i):等价于a[i],(列)指针值,指向第i行第0列(控制由行转为列,但仍为指针)。

*(*(a+i)):数组元素a[i][0]的值。

用a作指针访问数组元素a[i][j]的格式:

*(*(a+i)+j)注意:行指针是一个2级指针,如图所示。(2)从1维数组角度看,数组名a和第1维下标的每一个值,共同构成一组新的1维数组名a[0]、a[1]、a[2],它们均由4个元素组成。a+1a[2]a[1]a[0]a2321191715131197531===a+2200020162032a[0]a[0]+1a[0]+3a2000*(a[1]+2),*(*(a+1)+2)13a[0],*(a+0),*a2000**a1a+1,&a[1]2016**(a+1)9a[1],*(a+1),a[1]+02016a[1]+2,*(a+1)+2,&a[1][2]2024

C语言规定:数组名代表数组的地址,所以a[i]是第i行1维数组的地址,它指向该行的第0列元素,是一个以数组元素为单位进行控制的列指针:a[i]+j:(列)指针值,指向数组元素a[i][j]。*(a[i]+j):数组元素a[i][j]的值。如果有“inta[3][4],*p=a[0];”,则p+1指向下一个元素,如图所示。用p作指针访问数组元素a[i][j]的格式:*(p+(i*每行列数+j))2.行指针变量──指向由n个元素组成的一维数组的指针变量(1)定义格式

数据类型(*指针变量)[n];注意:“*指针变量”外的括号不能缺,否则成了指针数组——数组的每个元素都是一个指针──指针数组(本章第6节介绍)。(2)赋值

行指针变量=2维数组名|行指针变量;[案例9.6]使用行指针和列指针两种方式输出2维数组的任一元素。(1)使用行指针/*案例代码文件名:AL9_6_1.C*//*程序功能:使用行指针输出2维数组的任一元素*/main(){inta[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};

int(*pointer)[4],row,col;

pointer=a;printf(“Inputrow=”);scanf(“%d”,&row);printf(“Inputcol=”);scanf(“%d”,&col);printf(“a[%1d][%1d]=%d\n”,row,col,*(*(pointer+row)+col));}}程序运行情况:

Inputrow=1←┘Inputcol=2←┘array[1][2]=7思考题:本题也可以直接使用数组名a作指针,应如何修改?(2)使用列指针/*案例代码文件名:AL9_6_2.C*//*程序功能:使用列指针输出2维数组的任一元素*/main(){inta[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};

int*pointer,row,col; /*定义一个(列)指针变量pointer*/

pointer=a[0]; /*给(列)指针变量pointer赋值*/printf(“Inputrow=”);scanf(“%d”,&row);printf(“Inputcol=”);scanf(“%d”,&col);printf(“a[%1d][%1d]=%d\n”,row,col,*(pointer+(row*4+col)));} [程序演示]3.2维数组指针作函数参数一维数组的地址可以作为函数参数传递,多维数组的地址也可以作为函数参数传递。在用指针变量作形参以接受实参数组名传递来的地址时,有两种方法:①用指向变量的指针变量②用指向一维数组的指针变量。2008年9月1、有以下程序

#include

<stdio.h>

int

fun(int(*s)[4],intn,intk)

{

intm,i;

m=s[0][k];

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

if(s[i][k]>m)

m=s[i][k];

return

m;

}

main()

{inta[4][4]={{1,2,3,4},{11,12,13,14},{21,22,23,24},{31,32,33,34}};

printf("%d\n",fun(a,4,0));

}程序的运行结果是A)4

B)34

C)31

D)322010年3月1、若有定义int(*pt)[3];,则下列说法正确的是

A)定义了基类型为int的三个指针变量

B)定义了基类型为int的具有三个元素的指针数组pt

C)定义了一个名为*pt、具有三个元素的整型数组

D)定义了一个名为pt的指针变量,它可以指向每行有三个整数元素的二维数组9.3.5动态数组的实现在程序运行过程中,数组的大小是不能改变的。这种数组称为静态数组。静态数组的缺点是:对于事先无法准确估计数据量的情况,无法做到既满足处理需要,又不浪费内存空间。所谓动态数组是指,在程序运行过程中,根据实际需要指定数组的大小。在C语言中,可利用内存的申请和释放库函数,以及指向数组的指针变量可当数组名使用的特点,来实现动态数组。

温馨提示

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

评论

0/150

提交评论