文档库 最新最全的文档下载
当前位置:文档库 › C语言指针练习题

C语言指针练习题

一、知识点

1.掌握指针、地址、指针类型、空指针(NULL)等概念;

2.掌握指针变量的定义和初始化、指针的间接访问、指针的加减运算、指针变量比较运算和指针表达式;

3.掌握指针与数组、函数、字符串等的联系;

4.掌握动态空间操作(new,delete);

5.掌握引用参数的使用。

二、例题分析与解答

例题1:若有以下定义,则说法错误的是( )。

int a=100,*p=&a ;

A.声明变量p,其中*表示p是一个指针变量

B.变量p经初始化,获得变量a的地址

C.变量p只可以指向一个整形变量

D.变量p的值为100

答案:D

分析:有指针变量定义可知A、C说法是正确的,故不能选。在语句中&p=a,表示指针变量取得变量a地址,B说法也正确,也不能选择。D中不能说变量p的值为100,应该*p的值为100,所以选择D。

例题2:若有以下定义,则赋值正确的是( )。

int a ,b , *p;

float c, *q;

A.p=&c B.q=p C.p=NULL D.q=new int

答案:C

分析:指针变量使用规定,不同类型的指针变量不能赋值,也不能取得普通变量地址,故A、B不正确,不能选择。因为q是float类型指针变量,不能申请int 类型地址,D不正确,也不能选择。因为任何类型的指针变量都能取得NULL指针,所以C正确。

例题3:如果x是整型变量,则合法的形式是( )。

A.&(x+5) B.*x C.&*x D.*&x

答案:D

分析:因为C++语言表达式没有地址,A不正确。C++语言普通变量不能用*运算,因此B和C 也不正确。&x表示变量x的地址,*&x是x 地址的值,所以D正确。

例题4:若要建立如下关系,错误的语句组是( )。

span

style='mso-ignore:vglayout; ;z-index:1;left:0px;margin-left:144px;margin-top:1p x; width:256px;height:38px'

A. B. C. D.

int *p=&x, x; int x, p=&x; int *p, x=10; int *p, x;

*p=10; *p=10; *p=&x; p=&x ; x=10;

答案:A

分析:在变量类型说明语句中 *表示变量是指针变量,在其他语句中,*称为指针运算,用于访问指针所指向的对象的值,&称为取地址运算,用来得到一个对象的地址。故B、C、D都是正确的,不能选择。A中指针变量p取不到x地址,因为x还没有定义,所以选择A。

例题5:若有语句int a[10]={0,1,2,3,4,5,6,7,8,9},*p=a;则( )不是对a数组元素的正确引用(其中0≤i<10)。

A.p[i] B.*(*(a+i)) C.a[p-a] D.*(&a[i])

答案:B

分析:指针就变量p取得数组a的首地址,由指针与数组关系知,p[i]表示数组元素第i+1元素值,p[i]=a[i]正确,故A不能选。*(a+i)表示一维数组a第i+1元素值,*(*(a+i)表示对第i+1元素值再取值是错误操作,所以选B。a[p-a]=a[0]正确,故不能选择C。*(&a[i])也正确(见上题),也不能选D。

例题6:写出下列程序运行结果是( )。

#include

void main()

{

char ch[3][4]={“AAA”,”BB”,”CCC”},(*q)[4]=ch, *p;

// ch是二维数组, q是指向一维数组指针,并且一维数组每行只有4个字符//q并取得二维数组ch首地址

int i;

p=new char; //申请地址

*p=’b’; //装入字符b

*(*q+3)=*p;

for(i=0;i<3;i++) cout<

}

A. B. C. D.

AAAbBB AAAb AAA AAA

BB BB bBB BB

CCC CCC CCC CCC

答案:A

分析:二维字符数组初始化后值如下表:

执行语句*(*q+3)=*p后二维字符数组值:

在输出语句中q[0]输出是AAAbBB,q[1]输出是BB,q[2]输出CCC,只能选择A。

例题7:写出下列程序运行结果:

#include

void main()

{int *pn, n=10,m=20;

float *pf, px=3.14159,py=2.71828;

pn=&n;

*pn+=m;

cout<<”n 现在的值是:”<<*pn<

pf=&px;

py+=5*(*pf);

cout<<”py现在的值是:”<

}

运行结果是:

n 现在的值是: 30

pf 现在的值是:18.4262

分析:指针是通过在变量前加一个“*”来定义,使用用“*”加变量名存取指针所指的值,用运算“&”取变量的地址,但是不能存取无指向的指针所指向内容,这样会导致系统故障。

例题8:写出下列程序运行结果:

#include

void main()

{int I,*p,a[]={10,20,30,40,50,60};

p=a;

for(I=0;I<5;I++)

cout<<”a[“<

<<’\t’<<”*(p+”< }

运行结果:

a[0]=10 *(a+0)=10 *(p+0)=10 p[0]=10

a[1]=20 *(a+1)=20 *(p+1)=20 p[1]=20

a[2]=30 *(a+2)=30 *(p+2)=30 p[2]=30

a[3]=40 *(a+3)=40 *(p+3)=40 p[3]=40

a[4]=50 *(a+4)=50 *(p+4)=50 p[4]=50

a[5]=60 *(a+5)=60 *(p+5)=60 p[5]=60

分析:分析程序根据指针与数组关系,引用数据可以有四种不同的表示方法:使用数组下标变量;使用数据固有的指针——数组名间接引用;使用指向数组的指针的间接引用;使用指向数组的指针下标引用。

例题9:指出下列程序运行结果:

#include

int b[4][4]={{10,11,12,13},{14,15,16,17},{18,19,20,21},{22,23,24,25}};

void main()

{int (*a)[4],*p;

a=b; //指针变量a,取得二维数组第一行地址

p=a[1]; //指针变量p,取得二维数组第二行第一列地址

for( int I=1;I<=4;p=p+1,I++) //A行

cout<<*p<<'\t';

cout<

for( I=0;I<=3;I++) //B行

{cout<<*(*a+1)<<'\t'; a++;} //C行

cout<

}

运行结果是:

14 15 16 17

11 15 19 23

分析:根据题意,指针变量p取得二维数组第二行第一列地址,进行循环语句后,每循环一次,指针变量下移一个元素,A行循环输出是14,15,16,17。指向一维数组指针a,取得二维

数组第一行地址,由指向一维数组指针定义,*a+1表示该行第一列元素地址,*(*a+1)表示该地址的值,所以B行输出是11,15,19,23。

例题10:写出下列程序运行结果:

#include

void fun(int *& a, int &m)

{ a=new int[m]; //A

int * p=a;

for(int i=0;i

*p++=i*i+1;

}

void main()

{ int *b,n=5;

fun(b,n);

for(int i=0;i

cout< cout< delete[]b; //B

}

运行结果是:

1 2 5 10 17

分析:指针变量在函数main中没有取得地址,所以在A行中,对被调用函数fun给对应的形参指针变量申请地址,即指针变量b和形参指针变量p指向同一组地址。B行对申请地址释放。

例题11:下列函数change的功能是,将字符串中的小写字母转成大写字母,请填空。

#include

#include

void change( ) //1

{int i=0;

for(i=0; ;i++) //2

if(a[i]>='a'&&a[i]<='z')

; //3

}

void main()

{char p[80];

cout<<" \n";

cin.getline(p,80) ; //读一行字符,中间可以有空格

change(p);

cout<

}

如程序运行时得到以下结果:

请输入一行字符:

This is a book..

THIS IS A BOOK.

答案:(1)char *a 或 char a[80]

(2) a[i] 或a[i]!=’\0’

(3) a[i]= a[i] –32或a[i]-= a[i]

分析:

(1) 由指针和字符串关系知:当实参是数组,形参可以是字符串变量,也可以是字符

指针变量。

(2) 循环语句结束条件是字符标记’\0’。

(3) 大写字母的ASCII码比小室字母的ASCII码小32。

例题12:下列函数swap实现数据交换功能功能,请填空。

#include

void swap(int *p,int *q)

{int temp;

temp=*p;

; //1

; //2

}

void main()

{int a,b;

int *p1,*p2;

cout<<"请输入两个正数:";

cin>>a>>b;

p1=&a;

p2=&b;

swap(p1,p2);

cout<<"结果a和b的值:"<

}

如程序运行时得到以下结果:

请输入两个正数:10 20

结果a和b的值:20,10

答案:

(1)(1) *p=*q

(2)(2) *q=temp;

分析:实参和形参都是指针变量,所以指针变量p1和p指向同一个地址,同样p2和q也指向同一个地址。函数swap()是交换两个数,故应填写语句*p=*q、*q=temp。

例题13:下列函数sort实现对字符串按字典顺序由小到大排序,请填空。#include

#include

void sort( ) //1

{char ; //2

int i,j;

for(i=0;i

for(j=0;j

if(strcmp( ) //3

{ temp=p[j];

; //4

p[j+1]=temp;

}

}

void main() {

char *a[5]={"student","worker","cadre","soldier","apen"};

sort(a,5);

for(int i=0;i<5;i++)

cout<

}

程序运行结果如下:

apen

cadre

soldier

student

worker

答案:(1)char *p[],int n

(2)*temp

(3)p[j],p[j+1])>0

(4)p[j]=p[j+1]

分析:(1)由实参得知函数sort()有两个形参,根据上题得char *p[],int n。

(2)有下面语句temp=p[j]可以得到temp是字符中指针。

(3)根据冒泡排序方法和字符串比较函数得到p[j],p[j+1])>0。

(4)字符串指针可以通过赋值语句传递值,字符串变量不能够使用赋值语句传递值。

例题14:函数find功能是:在指针p所指数组中,查找值为x的元素,找到后,返回该元素的下标,否则返回-1,改正程序中语句错误,能够正确运行。

#include

#include

const int N=10;

int find(int *p,int n,int x) //1

{ int i ; // 2

*(p+n)=x; //3

while(*p+i!=x) //4

i++; //5

if(i!=n) //6

return 1; //7

else

return -1; //8

}

void main()

{int i,pos,x;

int *p=new int [N];

for(i=0;i

*(p+i)=rand()%50;

for(i=0;i

cout<<*(p+i)<<'\t';

cout<<"\ninput x: ";

cin>>x;

pos=find(p,N,x);

if(pos!=-1)cout<<"index= "<

MARGIN-LEFT: ,value="<<*(p+pos)<

else cout<<"No find!"<

}

答案:(1) 2行语句改为 int i=0;

(2) 4行语句改为 while(*(p+i)!=x);

(3) 7行语句改为 return i 。

分析:在函数find中,变量i没有赋初值,按照规则任意取值,所以程序不正确。在while 循环条件中*p+i表示指针p指向地址元素值加i,不能起着指针移动作用,改为*(p+i)表示数组第i个元素值起着顺序查找作用。在函数中如果找到查找元素返回其下标,7行应该是return i ,而不是return 1。

例题15:写一个函数,将一个n阶方阵转置。具体要求如下:

(1)初始化一个矩阵A(5×5),元素值取自随机函数,并输出。

(2)将其传递给函数,实现矩阵转置。

(3)在主函数中输出转置后的矩阵。(提示:程序中可以使用C++库函数rand( ),其功能是产生一个随机数0~65535,其头文件为stdlib.h)

分析:根据题目要求,本题的关键是实现矩阵的转置,指针变量p指向矩阵c,由数组存放规则和指针变量的规则,得到下列程序:

#include

#include

#include

int a[5][5],c[5][5]; //矩阵a、c定义为全局变量

void zc(int b[][5],int n); //函数声明语句

void main()

{int i,j;

srand(time(NULL)); //产生一个时间

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

for(j=0;j<5;j++)

*(*(a+i)+j)=rand()%100 ; //产生一个随机数

cout<<"自动生成矩阵为:\n";

for(i=0;i<5;i++) //输出自动生成的二维数组

{for(j=0;j<5;j++)

cout<<'\t'<<*(*(a+i)+j);

cout<

}

zc(a,5); //调用转置矩阵函数

cout<<"转置矩阵为:\n" ;

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

{for(j=0;j<5;j++)

cout<<'\t'<<*(*(c+i)+j);

cout<

}

}

void zc(int b[][5],int n)

{int i,j;

int (*p)[5];

p=c;

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

for(j=0;j<5;j++)

*(*(p+i)+j)=*(*(b+j)+i); // 转置

}

三、习题及参考答案

1.选择题:

(1)如果x是整型变量,则合法的形式是( )。

A.&(x+5) B.*x C.&*x D.*&x

答案:D

(2)若有语句int a[10]={0,1,2,3,4,5,6,7,8,9},*p=a;则( )不是对a数组元素的正确引用(其中0≤i<10)。

A.p[i] B.*(*(a+i)) C.a[p-a] D.*(&a[i])

答案:B

(3)以下程序的输出结果是( )。

#include

void main()

{ int a[3]={10,15,20}; // a[0]=10,a[1]=15,a[2]=20

int *p1=a,*p2=&a[1]; // p1取a[0]地址,p2取a[1]地址

*p1=*(p2-1)+5; // a[0]=15,a[1]=15,a[2]=20

*(p1+1)=*p1-5; // a[0]=15,a[1]=10,a[2]=20

cout<

}

A.5 B.10C.15 D.20

答案:B

分析:见程序注释

(4)执行以下程序段后,m的值为 ( )。

int a[2][3]={{1,2,3},{4,5,6}};

i nt m,*p=&a[0][0];

m=(*p)*(*(p+2))*(*(p+4));

A.15 B.14 C.13 D.12

答案:A

分析:C++语言,二维数组的存储方式在计算机中仍然是按一维数组存储,并按行优先,即是先存储第一行元素,接着存储第二行元素。语句p=&a[0][0]表示指针变量p取得二维数组第一个元素p[0][0]地址,注意不用语句p=a取二维数组首地址(同学考虑为什么?),*p、

*(p+2)、*(p+4)的值分别为1、3、5,所以m=15。

(5)以下程序的输出结果是( )。

#include

void fun(int x,int y,int *cp,int *dp)

{ cp=x+y; //*cp=30+50=80

dp=x-y; //*dp=30-50=-20

}

void main()

{ int a,b,c,d;

a=30,b=50;

fun(a,b,&c,&d);

cout<

}

A.50,30 B.30,50 C.80,-20 D.80,20

答案:C

分析:函数fun(a,b,&c,&d)中参数 a,b是传值,参数&c,&d是传地址,因此形参cp和实参c 共用一个存储空间,形参dp和实参d共用一个存储空间,所以改变指针变量cp所指向地址的值也就改变变量c的值,同样改变指针变量dp所指向地址的值也就改变变量d的值,因此选C。

(6)要求函数的功能是交换x和y中的值,且通过正确调用返回交换结果。能正确执行此功能的函数是( )。

A.funa(int *x,int *y) B.funb(int x,int y)

{ int *p=new int ; { int t;

p=*x; t=x;

*x=*y; x=y;

*y=*p; } y=t; }

C.func(int *x,int *y) D.fund(int x,int y)

{*x=*y; { *x=*x+*y;

*y=*x; *y=*x-*y;

} *x=*x-*y; }

答案:A

分析:按照C++语言规则,通过参数带回运算值,只能是传地址,不能是传值,B和D的参数是传值,故B和D不能选。C中传回值都是指针变量y所指向地址的值,C也不能选。

(7)以下程序的输出结果是( )。

#include

void main()

{ char *s="12134211";

int v1=0,v2=0,v3=0,v4=0;

for (int k=0;s[k];k++)

switch(s[k])

{ default:v4++;

case '1':v1++;

case '3':v3++;

case '2':v2++;

}

cout<

}

A.4,2,1,1 B.4,9,3,1 C.5,8,6,1 D.8,8,8,8

答案:C

分析:C++语言中的switch语句中,如果没有break语句,一旦满足某一条件进入,就一直运行到switch的结束,如在本题s[1]=’1’,除v1加1之外,v2和v3都要加1。故运行结果是“5,,8,6,1”,选择C。如果程序做下面修改:

switch(s[k])

{ default:v4++; break;

case '1':v1++; break;

case '3':v3++;break;

case '2':v2++;break;

}

运行结果是“4,2,1,1”,选择A。

(8)设有如下定义,下面关于ptr正确叙述是()。

int (*ptr)();

A.ptr是指向一维数组的指针变量

B.ptr是指向int 型数据的指针变量

C.ptr是指向函数的指针,该函数返回一个int型数据

D.ptr是一个函数名,该函数的返回值是指向int型数据的指针答案:C

分析:参照函数指针定义。

(9)若有如下语句:

int **pp,*p,a=10,b=20;

pp=&p; //二级指针pp取一级指针p地址

p=&a; //一级指针p取变量a地址

p=&b; //一级指针p取变量b地址

cout<<*p<<”,”<<**pp<

则输出结果是()。

A.10,20 B.10,10 C.20,10 D.20,20

答案:D

分析:见程序注释。

(10)设char **s;以下正确的表达式是()。

A.s=”computer”;B.*s=”computer”;C.**s=”computer”;

D.*s=’c’;

答案:C

分析:由char**s语句可知,**s表示是一个二级字符指针变量,*s是一个指向字符串的指针变量,故A、C、D都不正确,只有B是正确的。

2.编写程序,在堆内存中申请一个float型数组,把10个float型数据0.1、0.2、0.3、…、1.0赋予该数组,然后使用float型指针输出该数组的各元素值并求出其累加和。

#include

void main()

{ float *p= new float[10]; //在堆内申请一个float型数组

int i;

float sum=0.0;

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

{*(p+i)=(i+1)*.1; //给数组赋值0.1,0.2,……,1.0

cout<<*(p+i)<<'\t'; //输出数组值

sum+=*(p+i); //求和

}

cout<<"\n sum= "<

}

3.编写一个函数f,将传入此函数的直角坐标值转换为极坐标值,并返回主调函数中。求极坐标的公式是:

c=q=arctan(y/x)

若要将两值返回主调函数,有多种方式可以完成,请试之:

(1)(1) 两值均以指针形参带回。

void fun(double x,double y,double *c,double *q)

{ cout<

*c=sqrt(x*x+y*y);

cout<<*c<

*q=atan(y/x);

}

(2)由指针形参带回一个值,函数值返回另一个值。

double fun(double x,double y,double *p)

{double c;

c=sqrt(x*x+y*y);

*p=atan(y/x);

return c;

}

(3)两值均以引用形参返回。

(提示:程序中可以使用C++库函数sprt、pow及atan,它们的头文件为math.h)

void fun(double x,double y,double &a,double &b)

{ a=sqrt(x*x+y*y);

b=atan(y/x);

相关文档