C二级 第8章 指针
- 格式:docx
- 大小:49.61 KB
- 文档页数:9
c语言二级指针详解C语言中,指针是一种重要的数据类型,它可以指向另一个变量或者数据结构中的一个元素,并且可以进行不同种类的操作(如解引用、赋值、比较、运算等)。
在C语言中,指针本身也是一个变量,它具有一个内存地址,并且其值就是指向的地址。
而指针变量可以通过指定自己的类型来控制指向的变量或者数据结构元素的类型。
在C语言中,指针本身也可以被指针所指向,这样的指针就被称为“二级指针”或者“指向指针的指针”。
二级指针在一些情况下比普通指针更加灵活,比如当我们需要在函数内部进行指针变量的修改或者返回值时,就可以使用二级指针。
1、指向指针的指针需要使用两个星号(**)来声明,例如:int **p;2、在函数中传递指向指针的指针时,需要将变量的地址传递给函数,而函数需要使用指向指针的指针来访问实际的指针变量。
3、在使用二级指针时,我们需要防止指针变量指向非法内存地址,否则会导致程序出现意想不到的错误。
二级指针是C语言中非常重要的概念,尤其在函数调用和指针变量的修改或返回值时,更是非常有用。
不过,我们在使用二级指针时需要额外注意指向内存地址的合法性,否则会导致程序出现异常。
二级指针是指指向指针对象的指针,即指针的指针,它可以通过间接的方式访问一个指针变量所指向的地址,这种间接的访问方式可以增加程序的灵活性,从而使程序更加易于理解和维护。
1、动态内存管理在C语言中,动态内存分配是通过调用malloc函数来实现的,而释放动态内存则需要使用free函数。
在使用malloc函数分配内存时,它会返回一个指针,指向分配的内存空间的首地址,我们可以将这个指针赋值给一个普通的指针变量,然后通过这个普通指针变量来访问分配的内存空间。
不过,当我们使用malloc来分配一个指针数组时,我们就需要使用二级指针来存储这个指针数组的首地址。
int **p = (int **)malloc(sizeof(int *) * 10);for (int i = 0; i < 10; ++i) {p[i] = (int *)malloc(sizeof(int) * 10);}以上代码中,我们使用了二级指针来存储指向指针数组的地址,然后使用循环语句来为每一个指针分配空间。
全国计算机等级考试《二级C语言程序设计》复习全书【核心讲义+历年真题详解]最新资料,WORD格式,可编辑修改!目录第一部分备考指南......................................................第1章考试概述....................................................第2章复习技巧.................................................... 第二部分核心讲义......................................................【公共基础知识】....................................................第1章数据结构与算法..........................................第2章程序设计基础............................................第3章软件工程基础............................................第4章数据库设计基础..........................................【C语言程序设计】..................................................第1章程序设计基本概念........................................第2章C程序设计的初步知识....................................第3章顺序结构................................................第4章选择结构................................................第5章循环结构................................................第6章字符型数据..............................................第7章函数..................................................第8章地址和指针..............................................第9章数组..................................................第10章字符串.................................................第11章对函数的进一步讨论.....................................第12章C语言中用户标识符的作用域和存储类 .....................第13章编译预处理和动态存储分配...............................第14章结构体、共用体和用户定义类型...........................第15章位运算.................................................第16章文件................................................. 第三部分历年真题及详解................................................全国计算机等级考试《二级C语言程序设计》真题及详解(一)............全国计算机等级考试《二级C语言程序设计》真题及详解(二)............全国计算机等级考试《二级C语言程序设计》真题及详解(三)............全国计算机等级考试《二级C语言程序设计》真题及详解(四)............全国计算机等级考试《二级C语言程序设计》真题及详解(五)............全国计算机等级考试《二级C语言程序设计》真题及详解(六)............ 第四部分模拟试题及讲解................................................全国计算机等级考试《二级C语言程序设计》模拟试题及详解(一)........全国计算机等级考试《二级C语言程序设计》模拟试题及详解(二)........第一部分备考指南第1章考试概述一、考试简介全国计算机等级考试(National Computer Rank Examination,简称NCRE),是经原国家教育委员会(现教育部)批准,由教育部考试中心主办,面向社会,用于考查应试人员计算机应用知识与技能的全国性计算机水平考试体系。
1. 编写函数,其功能是对传送过来的两个浮点数求出和值与差值,并通过形参传送回调用函数。
部分代码如下:#include<stdio.h>void fun(float a,float b,float *m,float *n){}main(){float a,b,c,d;printf("请输入两个数:");scanf("%f",&a);scanf("%f",&b);fun(a,b,&c,&d);printf("%f+%f=%f\n",a,b,c);printf("%f-%f=%f\n",a,b,d);}2. 编写函数,其功能是对传送过来的三个数选出最大数和最小数,并通过形参传回调用函数。
#include<stdio.h>void fun(int a,int b,int c,int *m, int *n){}main(){int a,b,c,max,min;printf("请输入三个数:");scanf("%d%d%d",&a,&b,&c);fun(a,b,c,&max,&min);printf("最大数与最小数分别为:%d,%d",max,min);}3.从键盘输入3个数,调用fun函数,返回3个数中的最小数,放在m中。
不改变程序结构,补充完成编程。
#include<stdio.h>main(){float a,b,c;scanf(“%f%f%f”,&a,&b,&c);;printf(“%d”,m);}fun( ){}4.统计从键盘上输入字符个数,用@字符结束输入。
在主函数中显示结果。
#include<stdio.h>.main(){int n;;printf(“%d”,n);}count( ){}5. 从键盘上输如一个数x,调用函数ispr,判断是否为素数,若是,返回字符‘Y’若不是,返回‘N’。
1)设有定义:int n1=0,n2,*p=&n2,*q=&n1;,以下赋值语句中与n2=n1;语句等价的是A)*p=*q; B)p=q; C)*p=&n1; D)p=*q;2) 已定义以下函数int fun(int *p) 4{ return *p;}main(){ a=10,b=4; a=fun(&b); }fun函数返回值是A)不确定的值B)一个整数C)形参p中存放的值D)形参p的地址值3) 若有说明语句:double *p, a; 则能通过scanf语句正确给输入项读入数据的程序段是A)*p=&a; scanf("%lf",p); B)*p=&a; scanf{"%f",p);C)p=&a; scanf("%lf",*p); D)p=&a; scanf{"%lf",p);4) 有以下程序main(){ int a=1, b=3, c=5;int *p1=&a, *p2=&b, *p=&c;*p =*p1*(*p2);printf("%d\n",c);}执行后的输出结果是A)1 B)2 C)3 D)45)以下程序的输出结果是 3 5 。
#include<stdio.h>void swap( int *a, int *b ){ int *t ;t=a; a=b; b=t;}main(){ int i=3,j=5,*p=&i,*q=&j;swap(p,q); printf(“%d %d\n”,*p,*q);}(6) 设有定义:int n=0,*p=&n,**q=&p;则以下选项中,正确的赋值语句是A) p=1; B) *q=2; p=2; C) q=p; D) *p=5;int **q=&p; q=&p; *q=*(&p)=p(7) 有以下程序片段:void fun(char *a, char *b) a=&c1,b=&c2;{ a=b; (*a)++; } a=&c2; c2='b';main (){ char c1=‘A’, c2=‘a’, *p1, *p2;p1=&c1;p2=&c2;fun(p1,p2);printf(“%c%c\n”,c1,c2);}程序运行后的输出结果是A) Ab B) aa C) Aa D) Bb(8) 已定义以下函数int *fun (int *p) p=&i;{ return p; }main(){ int i,*p=&i;int *q;q=fun(p); }该函数的返回值是A) 不确定的值B) 形参p中存放的值C) 形参p所指存储单元中的值D) 形参p的地址值(9) 有以下程序段片段:main(){ int a=5, *b, **c;c=&b; b=&a; c=&(&a); **c=**(&&a)……}程序在执行了c=&b; b=&a;语句后,表达式:**c的值是A) 变量a的地址B) 变量b中的值C) 变量a中的值D) 变量b的地址(10) 有以下程序片段:int *f(int *x,int *y) x=p=&a y=q=&b;{ if(*x<*y) a<b;return x;elsereturn y;}main(){ int a=7,b=8,*p,*q,*r;p = &a;q = &b;r = f(p,q); =&aprintf(“%d,%d,%d”,a,b,*r);}执行后输出结果是A) 7,8,8 B) 7,8,7 C) 8,7,7 D) 8,7,8(11) 有以下程序片段:void fun(char *c,int d) c=&b,d='A'{ *c=*c+1; d=d+1; *c='C' d='B'printf(“%c,%c,”,*c,d);}main(){ char a='A', b='B';fun(&b, a); printf(“%c,%c\n”,a,b);}程序运行后的输出结果是C,B,A,C(12) 下列程序段的输出结果是void fun(int *x, int *y) x=&m.y y=&m.x &m.y=3 &m.x=4{ printf(“%d %d”, *x, *y); *x=3; *y=4;}main(){ int x=1,y=2;fun(&y, &x);printf(“%d %d”,x, y);}A) 2 1 4 3 B) 1 2 1 2C) 1 2 3 4 D) 2 1 1 2(13) 下列程序的运行结果是A) 6 3 B) 3 6 C) 编译出错D) 0 0以下是引用片段:void fun(int *a, int *b) a=&m.a b=&m.b{ int k;k=a; a=b; b=k;}main(){ int a=3, b=6, *x=&a, *y=&b;fun(x,y);printf(“%d %d”, a, b);}(14) 若有以下定义和语句:double r=99,*p=&r;*p=r;则以下正确的叙述是A) 以上两处的*p含义相同,都说明给指针变量p赋值B) 在"double r=99,*p=&r;"中,把r的地址赋值给了p所指的存储单元C) 语句"*p=r;"把变量r的值赋给指针变量pD) 语句"*p=r;"取变量r的值放回r中(15) 以下程序运行后,a的值是A) 4 B) 1 C) 0 D) 运行时出错,a无定值以下是引用片段:main(){ int a,k=4,m=6,*p1=&k,*p2=&m;a=(p1= =&m);printf("%d\n",a);}(16) 若有定义和语句:int **pp, *p, a=10, b=20;pp=&p;p=&a; *p=10p=&b; *p=20 **pp=**(&p)=*p=20printf("%d\n",*p,**pp);则输出结果是:A)10,20 B)10,10 C)20,10 D)20,20(17) 以下程序的输出结果是以下是引用片段:#includesubl(char a,char b) {char c; c=a;a=b;b=c;}sub2(char* a,char b) {char c; c=*a;*a=b;b=c;}sub3(char* a,char*b) {char c; c=*a;*a=*b;*b=c;}main(){char a,b;a='A'; b='B';sub3(&a, &b);putchar(a); putchar(b); BAa='A'; b='B';sub2(&a,b);putchar(a); prtchar(b); BBa='A'; b='B';sub1(a,b);putchar(a); putchar(b); AB}A) BABBAB B) ABBBBAC) BABABA D) BAABBA二、填空题:(1) 有以下程序片段:void f( int y, int *x) y=4 x=&m.x{y=y+*x; *x=*x+y;} y=6 m.x=8main( ){ int x=2,y=4;f(y, &x);printf(“%d %d\n”,x,y);}。
计算机二级C语言习题集汇总及答案目录第一章C语言基础知识第二章C语言程序设计的初步知识第三章顺序结构程序设计第四章选择结构程序设计第五章循环结构程序设计第六章数组第七章函数第八章指针第九章结构体与共用体第十章文件附录1 预处理命令附录2 位运算模拟试题一模拟试题二模拟试题三模拟试题四模拟试题五第一章答案第二章答案第三章答案第四章答案第五章答案第六章答案第七章答案第八章答案第九章答案第十章答案附录1 答案附录2 答案模拟试题一答案模拟试题二答案模拟试题三答案模拟试题四答案模拟试题五答案第一章C语言基础知识一、选择题1.C语言规定,必须用C 作为主函数名。
(0级)A)Function B)include C)main D)stdio 2.一个C程序可以包含任意多个不同名的函数,但有且仅有一个,一个C程序总是从 B 开始执行。
(0级)A)过程B) 主函数C)函数D)include3. A 是C程序的基本构成单位。
(0级)A)函数B) 函数和过程C) 超文本过程D) 子程序4.下列说法正确的是C 。
(0级)A) 一个函数的函数体必须要有变量定义和执行部分,二者缺一不可B) 一个函数的函数体必须要有执行部分,可以没有变量定义C) 一个函数的函数体可以没有变量定义和执行部分,函数可以是空函数D) 以上都不对5.下列说法正确的是D 。
(0级)A) main函数必须放在C程序的开头B) main函数必须放在C程序的最后C) main函数可以放在C程序的中间部分,但在执行C程序时是从程序开头执行的D) main函数可以放在C程序的中间部分,但在执行C程序时是从main函数开始的6.下列说法正确的是 C 。
(0级)A) 在执行C程序时不是从mian函数开始的B) C程序书写格式严格限制,一行内必须写一个语句C) C程序书写格式自由,一个语句可以分写在多行上D) C程序书写格式严格限制,一行内必须写一个语句,并要有行号7.在C语言中,每个语句和数据定义是用C 结束。
第八章指针的使用【学习目标】本章将详细介绍在C语言中如何使用指针。
学习要点包括如下几点:(1)掌握指针和指针变量的概念,了解指针变量的特点以及直接访问数据和间接访问数据的原理。
(2)掌握指针变量的定义、赋值方法及指针运算符的使用,熟练运用指针访问简单变量。
(3)熟悉指针和一维数组的关系,掌握指向一维数组的指针变量的定义方法,熟练使用指针变量访问一维数组元素。
(4)了解指针与字符串的关系,能熟练使用指针处理字符串。
(5)熟练掌握用指针变量作函数的参数时函数的定义和调用方法、数组名作函数的参数用法。
(6)指向指针的指针的运用。
【学习导航】本章的在整个课程中的位置如图5-1所示。
图8-1 本章学习导航在本书的第一章介绍C语言有一个灵活性的特点,那么它的灵活性具体体现在哪里呢?其实就是指针。
指针是C语言的精华部分,通过利用指针,我们能很好地利用内存资源,使其发挥最大的效率。
有了指针技术,我们可以描述复杂的数据结构,对字符串的处理可以更灵活,对数组的处理更方便,使程序的书写简洁,高效。
8.1 地址和指针指针是C语言的一种数据类型,类似于整型、字符型等。
既然指针也是一种类型,那么也可以定义该类型的变量,称为指针变量。
指针变量和其他类型的变量的区别是:指针变量存储的是地址。
所以要学好指针,就一定要明白数据在内存中是如何存储的。
计算机所有数据都是存储在存储器里,系统的内存可看作编了号的小房间,如果要取房间的东西(读取数据)就需要得到房间编号。
地址就是内存区中对每个字节的编号。
下面通过两个整型变量来说明。
整型变量x、y(基本整型需4个字节)在内存中的存储如图8-2所示(假设内存编号是从2000开始)。
把变量所占用的存储单元首字节的地址作为变量的地址。
C语言中利用取地址运算符“&”获取变量的存储地址。
例如,&c将返回c的首地址;&x将返回x的首地址。
2000H2004H2008H2012H...图8-2 变量x和y在内存中的存储图8-2中2000H和2004H就是内存单元的地址。
1.以下定义语句中正确的是A) int a=b=0; B) char A=65+1,b='b';C) float a=1,*b=&a,*c=&b; D) double a=0.0; b=1.1;参考答案:B【解析】A选项语句中b变量还没有定义不能直接用于给a变量赋值。C选项语句中*b、*c表示的是一个实型变量的地址,不能再将&b赋值给指针型变量c。D选项语句中a=0.0后面应该为逗号,不能是分号。2.有以下程序#include <stdio.h>void f(int *p,int *q);main(){ int m=1,n=2,*r=&m;f(r, &n);printf("%d,%d",m,n);}void f(int *p,int *q){ p=p+1;*q=*q+1;}程序运行后的输出结果是A) 2,3 B) 1,3 C) 1,4 D) 1,2参考答案:B【解析】在f(int *p,int*q)函数中,执行p=p+1是将p所对应的地址加1,而*q=*q+1是将q所指向的n的地址所对应的值加1,所以m的得知所对应的值没有变,而n的值则为3了。
因此B选项正确。
3.以下叙述中正确的是A) 如果p是指针变量,则&p是不合法的表达式B) 如果p是指针变量,则*p表示变量p的地址值C) 在对指针进行加、减算术运算时,数字1表示1个存储单元的长度D) 如果p是指针变量,则*p+1和*(p+1)的效果是一样的参考答案:C【解析】B选项中,如果p是指针变量,则*p表示变量p所指向的地址的值;A选项中,如果p是指针变量,则&p表示变量p的地址;D选项中,如果p是指针变量,*p+1表示将p所指的值加上1,而*(p+1)表示的是先将指针右移一位再取所指向变量的值。
因此C选项正确。
4.以下叙述中正确的是A) 基类型不同的指针变量可以相互混用B) 函数的类型不能是指针类型C) 函数的形参类型不能是指针类型D) 设有指针变量为double *p,则p+1 将指针p移动8个字节参考答案:D【解析】B选项中,所谓函数类型是指函数返回值的类型。
在C语言中允许一个函数的返回值是一个指针(即地址),这种返回指针值的函数称为指针型函数;C选项中,函数的参数不仅可以是整型、实型、字符型等数据,还可以是指针类型;A选项中,虽然不同基类型的指针变量占用字节数是相同的,但是不能混用。
因此D选项正确。
5.如果定义float a[10], x;则以下叙述中正确的是C) 三个表达式a[1]、*(a+1)、*&a[1]表示的意思完全不同D) 表达式*&a[1]是非法的,应该写成*(&(a[1]))参考答案:A【解析】B选项中,表达式a+1不是非法的;C选项中,*(a+1)即指a[1];D选项中,*&a[1]不是非法的。
因此A选项正确。
6.以下叙述中错误的是()。
A) 可以给指针变量赋一个整数作为地址值B) 函数可以返回地址值C) 改变函数形参的值,不会改变对应实参的值D) 当在程序的开头包含头文件stdio.h时,可以给指针变量赋NULL参考答案:A【解析】不能将一个整数直接赋给指针变量作为地址,所以A)是错误的。
函数的返回值可以是地址,即指针。
函数调用中形参值的变化不会传递给实参。
7.设已有定义:float x;,则以下对指针变量p进行定义且赋初值的语句中正确的是()。
A) int *p=(float)x;B) float *p=&x;C) float p=&x;D) float *p=1024;参考答案:B【解析】指针是用来存放地址的变量,用(类型名*指针变量名)的形式定义。
赋值时应将某个变量地址即&x 赋给指针变量,所以选择B)。
8.若有定义语句:double a,*p=&a ;以下叙述中错误的是()。
A) 定义语句中的*号是一个间址运算符B) 定义语句中的*号是一个说明符C) 定义语句中的p只能存放double类型变量的地址D) 定义语句中,*p=&a把变量a的地址作为初值赋给指针变量p参考答案:A【解析】在变量定义double a,*p=&a ;中,* 号是一个指针运算符,而非间址运算符,所以A)错误。
9.有以下程序#include <stdio.h>main(){ int a=1, b=3, c=5;int *p1=&a, *p2=&b, *p=&c;*p =*p1*(*p2);printf("%d\n",c);}执行后的输出结果是A) 1 B) 2 C) 3 D) 4参考答案:C【解析】该程序中int *p1=&a, *p2=&b, *p=&c;指定义三个指针变量,并赋值,即使p1指向a;p2指向b;p指向c。
*p=*p1*(*p2);该条语句是给p所指的存储单元c赋值,就是p1所指的存储单元的值,即a的值,与p2所指的存储单元b的值相乘,也就是c=a*b,等价于c=1*3=3;因此C选项正确。
10.以下叙述中正确的是A) int* p1; int ** p2; int *p3;都是合法的定义指针变量的语句B) 指针变量只能通过求地址运算符(&) 来获得地址值C) 语句p=NULL;与p=\0;是等价的语句D) 语句p=NULL;执行后,指针p指向地址为0的存储单元参考答案:A地址值,还可以通过标准函数获得地址值;C选项中,p=NULL;和p=0;或p='\0';等价;D选项中,语句p=NULL;执行后,指针p并不是指向地址为0的存储单元,而是具有一个确定的值-"空"。
因此A选项正确。
11.以下叙述中正确的是A) 即使不进行强制类型转换,在进行指针赋值运算时,指针变量的基类型也可以不同B) 如果企图通过一个空指针来访问一个存储单元,将会得到一个出错信息C) 设变量p是一个指针变量,则语句p=0;是非法的,应该使用p=NULL;D) 指针变量之间不能用关系运算符进行比较参考答案:B【解析】A选项描述不正确,指针变量的赋值只能赋予地址,决不能赋予任何其它数据,否则将引起错误;C选项中,p=NULL;和p=0;是等价的;D选项中,指向同一数组的两指针变量进行关系运算可表示它们所值数组元素之间的关系。
因此B选项正确。
12.若有定义语句:int a[2][3],*p[3];则以下语句中正确的是A) p=a; B) p[0]=a; C) p[0]=&a[1][2]; D) p[1]=&a;参考答案:C【解析】A选项错误,因为p是指向一个指针数组,作为数组名,不能指向别的地方。
B选项错误,因为p[0]是一个int指针,也就是int*;而a是一个指向指针的指针int**。
C选项正确,因为p[0]是一个int*,a[1][2]是int,&a[1][2]是int*,类型吻合。
D选项错误,因为a作为数组名,不能取地址。
即使能取,p[1]是int*,&a 是int***,类型不对。
因此C选项正确。
13.在32位编译器上,设有定义char *str1 = "Hello", str2[] = "Hello"; ,则以下语句printf("%d %d", sizeof(str1), sizeof(str2));的输出结果是A) 5 6 B) 5 5 C) 6 6 D) 4 6参考答案:D【解析】本题主要考查了指向字符串的指针和字符数组,str1为一个字符指针,所以sizeof为4,str2为字符数组,其中包含6个字符,所以答案为4 614.有以下程序:#include <stdio.h>main(){ int n,*p=NULL;*p=&n;printf("Input n:");scanf("%d",&p);printf("output n:");printf("%d\n",p);}该程序试图通过指针p为变量n读入数据并输出,但程序有多处错误,以下语句正确的是()A) int n,*p=NULL B) *p=&n;C) scanf("%d",&p) D) printf("%d\n",p);参考答案:A【解析】选项B)的正确写法应为p=&n;选项C)的正确写法应为scanf("%d",p);选项D)的正确写法应为printf("%d\n",*p)。
15.若有定义语句:double x,y,*px,*py;执行了px=&x;py=&y;之后,正确的输入语句是()。
A) scanf("%lf %le",px,py);B) scanf("%f %f" &x,&y);C) scanf("%f %f",x,y);D) scanf("%lf %lf",x,y);参考答案:Ascanf("%lf %lf",x,y);应为scanf("%lf %lf",&x,&y);。
16.以下程序段完全正确的是A) int *p; scanf("%d", &p); B) int *p; scanf("%d", p);C) int k, *p=&k; scanf("%d", p); D) int k, *p; *p=&k; scanf("%d", p);参考答案:C【解析】A选项中错在没有对指针进行初始化,无效指针,并且在scanf("%d",&p)中无需再进行取地址操作;B选项中没有对指针进行初始化,无效指针;D选项中语句*p=&k;的左端*p 是指针所指内存空间的值,&k 是地址,应为p=&k。
因此C选项正确。
17.若有以下程序#include <stdio.h>int *f(int *s,int *t){ int *k;if (*s < *t){ k = s; s=t; t=k; }return s;}main(){ int i=3, j=5, *p=&i, *q=&j, *r;r=f(p,q); printf("%d,%d,%d,%d,%d\n", i, j, *p, *q, *r);}则程序的输出结果是A) 3,5,5,3,5 B) 3,5,3,5,5 C) 5,3,5,3,5 D) 5,3,3,5,5参考答案:B【解析】在主函数中分别给整型变量i、j和指针型变量p、q赋初值,并声明指针变量r;调用f函数,并将实参变量p和q的值传递给形参变量s和t,并且f函数是指针型函数,即函数的返回值将是一个地址。