全国计算机二级:C语言之指针、数组和函数
- 格式:doc
- 大小:31.00 KB
- 文档页数:4
全国二级计算机考试c语言试题及答案全国二级计算机考试C语言试题及答案一、选择题(每题1分,共10分)1. 在C语言中,以下哪个选项是合法的变量名?A. 2variableB. _intC. intD. variable2答案:B2. 下列关于C语言中数组的描述,正确的是:A. 数组的大小在定义后可以改变B. 数组的索引从0开始C. 数组可以存储不同类型的数据D. 数组必须在程序开始时定义答案:B3. 在C语言中,以下哪个关键字用于定义一个函数?A. structB. intC. voidD. return答案:C4. C语言中,以下哪个运算符用于取地址?A. *B. &C. %D. #答案:B5. 下列关于C语言中指针的描述,错误的是:A. 指针可以存储地址B. 指针可以被赋值为NULLC. 指针可以存储任何类型的数据D. 指针可以被解引用答案:C6. 在C语言中,以下哪个选项是正确的注释方式?A. // 这是注释B. /* 这是注释 */C. //* 这是注释 */D. /* 这是注释答案:A7. C语言中,以下哪个函数用于将字符串复制到另一个字符串?A. strcpyB. strcatC. strcmpD. strlen答案:A8. 在C语言中,以下哪个选项是正确的文件操作函数?A. fopenB. fcloseC. fprintfD. All of the above答案:D9. C语言中,以下哪个关键字用于定义一个结构体?A. structB. unionC. enumD. typedef答案:A10. 在C语言中,以下哪个选项是正确的条件语句?A. if (x)B. if xC. if (x == 0)D. if (x != 0)答案:A二、填空题(每题2分,共10分)1. 在C语言中,______关键字用于声明一个变量。
答案:int2. 一个C语言程序的执行从______函数开始。
理解C语⾔(⼀)数组、函数与指针1 指针⼀般地,计算机内存的每个位置都由⼀个地址标识,在C语⾔中我们⽤指针表⽰内存地址。
指针变量的值实际上就是内存地址,⽽指针变量所指向的内容则是该内存地址存储的内容,这是通过解引⽤指针获得。
声明⼀个指针变量并不会⾃动分配任何内存。
在对指针进⾏间接访问前,指针必须初始化: 要么指向它现有的内存,要么给它分配动态内存。
对未初始化的指针变量执⾏解引⽤操作是⾮法的,⽽且这种错误常常难以检测,其结果往往是⼀个不相关的值被修改,并且这种错误很难调试,因⽽我们需要明确强调: 未初始化的指针是⽆效的,直到该指针赋值后,才可使⽤它。
int *a;*a=12; //只是声明了变量a,但从未对它初始化,因⽽我们没办法预测值12将存储在什么地⽅int *d=0; //这是可以的,0可以视作为零值int b=12;int *c=&b;另外C标准定义了NULL指针,它作为⼀个特殊的指针常量,表⽰不指向任何位置,因⽽对⼀个NULL指针进⾏解引⽤操作同样也是⾮法的。
因⽽在对指针进⾏解引⽤操作的所有情形前,如常规赋值、指针作为函数的参数,⾸先必须检查指针的合法性- ⾮NULL指针。
解引⽤NULL指针操作的后果因编译器⽽异,两个常见的后果分别是返回置0的值及终⽌程序。
总结下来,不论你的机器对解引⽤NULL指针这种⾏为作何反应,对所有的指针变量进⾏显式的初始化是种好做法。
如果知道指针被初始化为什么地址,就该把它初始化为该地址,否则初始化为NULL在所有指针解引⽤操作前都要对其进⾏合法性检查,判断是否为NULL指针,这是⼀种良好安全的编程风格1.1 指针运算基础在指针值上可以进⾏有限的算术运算和关系运算。
合法的运算具体包括以下⼏种: 指针与整数的加减(包括指针的⾃增和⾃减)、同类型指针间的⽐较、同类型的指针相减。
例如⼀个指针加上或减去⼀个整型值,⽐较两指针是否相等或不相等,但是这两种运算只有作⽤于同⼀个数组中才可以预测。
国家二级C语言机试(函数和数组)模拟试卷22国家二级C语言机试(函数和数组)模拟试卷22(总分:58.00,做题时间:90分钟)一、选择题(总题数:29,分数:58.00)1.有以下程序#include main(){ int c[6]={10,20,30,40,50,60},*p,*s;p=c;s=&c[5];printf("%d\n",s-p);} 程序运行后的输出结果是(分数:2.00)A.50B.6C.5 √D.60解析:解析:主函数中指针变量p指向数组c,s保存了数组最后一个元素的地址,那么s中为两个地址之间的元素差5。
2.以下叙述中正确的是(分数:2.00)A.一条语句只能定义一个数组B.数组说明符的一对方括号中只能使用整型常量,而不能使用表达式C.每个数组包含一组具有同一类型的变量,这些变量在内存中占有连续的存储单元√D.在引用数组元素时,下标表达式可以使用浮点数解析:解析:数组的定义格式:类型说明符数组名[整型常量表达式]….;可以同时定义多个类型相同的数组,之间以逗号分隔开,数组的类型表明了数组中元素的数据类型,数组中所有元素的类型相同,数组经过定义以后就可使用,编译程序将对其分配一片连续的存储空间进行连续存储。
C语言中只能单个引用数组元素而不能一次引用整个数组。
引用格式为:数组名[下标],引用元素时,需要注意下标只能为整型常量或整型表达式。
3.以下叙述中正确的是(分数:2.00)A.语句int a[]={0};是不合法的,遗漏了数组的大小B.语句char a[2]={"A","B"};是合法的,定义了一个包含两个字符的数组C.语句int a[8]={0};是合法的√D.语句char a[3];a="AB";是合法的,因为数组有三个字符空间的容量,可以保存两个字符解析:解析:当系统为所定义的数组在内存中开辟~串连续的存储单元时,这些存储单元中并没有确定的值,可以在定义语句中为所定义数组的各个元素赋初值。
【导语】2019年3⽉计算机⼆级考试备考正在进⾏中,为了⽅便考⽣及时有效的备考,那么,为您精⼼整理了2019年全国计算机⼆级C语⾔考点:函数的类型和返回值,欢迎⼤家的关注。
如想获取更多计算机⼆级考试的模拟题及备考资料,请关注的更新。
函数的类型和返回值 1.函数的类型由函数定义中的函数返回值的类型名确定,函数的类型可以是任何简单类型,如整型、字符型、指针型、双精度型等,它指出了函数返回值的具体类型。
当函数返回的是整型值时,可以省略函数类型名。
当函数只完成特定的操作⽽没有或不需要返回值时,可⽤类型名void(空类型)。
2.函数返回值就是return语句中表达式的值。
当程序执⾏到return语句时,程序的流程就返回到调⽤该函数的地⽅(通常称为退出调⽤函数),并带回函数值。
7.4形式参数与实际参数,参数值的传递 1.在函数定义中,出现的参数名称为形参(形式参数),在调⽤函数时,使⽤的参数值称为实参(实际参数)。
2.调⽤函数和被调⽤函数之间的参数值的传递是″按值″进⾏的,即数据只能从实参单向传递给形参。
也就是说,当简单变量作为实参时,⽤户不能在函数中改变对应实参的值。
7.5函数的正确调⽤(嵌套调⽤,递归调⽤) 1.调⽤函数时,函数名必须与被调⽤的函数名字完全⼀样。
实参的个数与类型和形参的个数与类型⼀致。
2.C语⾔规定:函数必须先定义,后调⽤,也就是被调⽤函数必须在调⽤之前加以说明,或被调⽤函数整个放在调⽤函数之前。
但对返回值类型为int或char类型的函数可以放在调⽤函数的后⾯。
3.C语⾔中函数定义都是互相平⾏、独⽴的,C语⾔不允许嵌套定义函数,但允许嵌套调⽤函数,也就是说,在调⽤⼀个函数的过程中,⼜调⽤另⼀个函数。
4.在C程序中,调⽤⼀个函数的过程中⼜出现直接或间接地调⽤该函数本⾝,称为函数的递归调⽤。
5.递归调⽤函数是C语⾔的特点之⼀,有时递归调⽤会使求解的问题变得更简单明了。
数组下标的下限是0。
全国计算机二级C语言公共基础知识一、数据结构与算法1、完全二叉树是属于非线性结构,但其最佳存储方式是顺序存储方式2、顺序存储结构中可能根节点不唯一,故可能不是线性结构3、算法的有穷性是指,算法中的操作步骤为有限个,且每个步骤都能在有限时间内完成4、法复杂度包括算法的时间复杂度和算法的空间复杂度。
算法设计必须考虑执行算法所需要的资源,即时间与空间复杂度5、算法的优劣取决于算法复杂度,与程序的环境无关,当算法被编程实现之后,程序的运行受到计算机系统运行环境的限制6、循环队列中,由于指针超过队列地址最大值时会移动到队列最小地址处,所以队头指针可以大于也可以小于队尾指针7、链式存储结构中每个结点都由数据域与指针域两部分组成,增加了存储空间8、循环队列是队列的一种顺序存储结构,用队尾指针rear指向队列中的队尾元素,用排头指针front指向排头元素的前一个位置9、设循环队列为Q(1: m),其初始状态为front=rear=m。
经过一系列入队与退队运算后,front= X,rear= Y。
现要在该循环队列中寻找最大值的元素,最坏情况下需要比较的次数为(1)若X>Y,则次数为m-(Y-X)-1(2)若X<Y,则次数为Y-X-110、循环队列中的元素个数与队头指针和队尾指针的变化而变化11、队列的修改是依先进先出的原则进行的12、设计算法时不仅要考虑对数据对象的运算和操作,还要考虑算法的控制结构13、顺序表具有以下两个基本特征:(1)线性表中所有元素所占的存储空间是连续的;(2)线性表中各数据元素在存储空间中是按逻辑顺序依次存放的。
(3)在顺序表中,每个元素占有相同的存储单元14、设栈的顺序存储空间为S(0:49),栈底指针bottom=X,栈顶指针top=Y(指向栈顶元素)。
则栈中的元素个数为X-Y+115、设栈的顺序存储空间为S(1: m),初始状态为top=m+1(X)。
全国计算机等级考试(二级c语言)试卷分析一、选择题(每小题1分,共40小题,共40分)前面的10道题涉及计算机基础知识(数据结构、数据库、软件工程等方面知识),在这里就不针对计算机基础知识部分进行分析。
11.以下叙述中正确的是( )。
A.在C语言程序中,main函数必须放在其他函数的最前面B.每个后缀为C的C语言源程序都可以单独进行编译C.在C语言程序中,只有main函数才可单独进行编译D.每个后缀为.C的C语言源程序都应该包含一个main函数【解析】B。
C语言是一种成功的系统描述语言,具有良好的移植性,每个后缀为.C的C语言源程序都可以单独进行编译;C语言程序中,不管包含多少个后缀为.C的程序文件,但是一定有且仅有一个main函数,而且main函数在程序中可以放在任何其他函数之前或之后。
12.C语言中的标识符分为关键字、预定义标识符和用户标识符,以下叙述正确的是( )。
A.预定义标识符(如库函数中的函数名)可用做用户标识符,但失去原有含义B.用户标识符可以由字母和数字任意顺序组成C.在标识符中大写字母和小写字母被认为是相同的字符D.关键字可用做用户标识符,但失去原有含义【解析】A。
用户标识符不能以数字开头,C语言中标识符是区分大小写的,关键字不能用做用户标识符。
13.以下选项中表示一个合法的常量是(说明:符号口表示空格)( )。
A.9口9口9B.0XabC.123E0.2D.2.7e【解析】B。
当用指数形式表示浮点数据时,E的前后都要有数据,并且E的后面数要为整数;整型常量:0123表示八进制整型常量,0xab 表示十六进制整型常量,123为十进制整型常量,123L表示长整型常量,123U表示无符号整型常量,123UL表示无符号长整型常量。
答案A没有这种常量,如果加上双引号是可以表示字符串常量。
14.C语言主要是借助以下哪个功能来实现程序模块化?( )A.定义函数B.定义常量和外部变量C.三种基本结构语句D.丰富的数据类型【解析】A。
2020年全国计算机等级考试二级C语言必考知识点总结【完美版】C语言最重要的知识点总体上必须清楚的:1)程序结构是三种:顺序结构、选择结构(分支结构)、循环结构。
2)读程序都要从main()入口,然后从最上面顺序往下读(碰到循环做循环,碰到选择做选择),有且只有一个main函数。
3)计算机的数据在电脑中保存是以二进制的形式.数据存放的位置就是他的地址.4)bit是位是指为或者1。
byte是指字节,一个字节=八个位.概念常考到的:1、编译预处理不是C语言的一部分,不占运行时间,不要加分号。
C语言编译的程序称为源程序,它以ASCII数值存放在文本文件中。
2、define PI 3.;这个写法是错误的,一定不能出现分号。
3、每个C语言程序中main函数是有且只有一个。
4、在函数中不可以再定义函数。
5、算法:可以没有输入,但是一定要有输出。
6、break可用于循环结构和switch语句。
7、逗号运算符的级别最低,赋值的级别倒数第二。
第一章C语言的基础知识第一节、对C语言的根蒂根基熟悉1、C语言编写的程序称为源程序,又称为编译单元。
2、C语言书写格式是自由的,每行可以写多个语句,可以写多行。
3、一个C语言程序有且只有一个main函数,是程序运转的出发点。
第二节、熟悉vc++1、VC是软件,用来运行写的C语言程序。
2、每一个C语言程序写完后,都是先编译,后链接,末了运转。
(.c---.obj---.exe)这个进程中注意.c和.obj文件时没法运转的,只有.exe文件才可以运转。
(常考!)第三节、标识符1、标识符(必考内容):合法的要求是由字母,数字,下划线组成。
有其它元素就错了。
而且第一个必须为字母或则是下划线。
第一个为数字就错了2、标识符分为枢纽字、预定义标识符、用户标识符。
枢纽字:不可以作为用户标识标记。
main define scanf printf都不是枢纽字。
利诱你的地方If是可以做为用户标识符。
全国计算机等级考试二级C语言1. 前言全国计算机等级考试是由中国电子学会主管、中国人力资源和社会保障部批准的全国性计算机等级考试。
考试内容覆盖计算机应用基础知识和实际应用能力。
本文档将介绍全国计算机等级考试二级C语言的相关内容。
2. 考试概述全国计算机等级考试二级C语言是面向具备一定C语言基础的考生的等级考试。
考试内容涉及C语言的基本语法、流程控制、函数、数组、指针、文件操作等知识点。
考试形式为闭卷考试,主要通过选择题和编程题来考察考生的理论知识和实践能力。
3. 考试内容全国计算机等级考试二级C语言的考试内容主要包括以下几个方面:3.1 C语言基础•语言的组成与结构•数据类型与变量•运算符与表达式•输入输出函数•注释与预处理指令3.2 流程控制•顺序结构•分支结构•循环结构3.3 函数•函数的定义与声明•函数的调用与返回•函数的参数与传递•递归函数3.4 数组•数组的定义与初始化•数组的访问与操作•多维数组•字符数组与字符串处理3.5 指针•指针的概念与基本操作•指针与数组•指针与函数•指针与字符串3.6 文件操作•文件的打开与关闭•文件的读写操作•文件指针的定位•文件的错误处理4. 考试准备为了顺利通过全国计算机等级考试二级C语言,考生需要做以下准备工作:•学习C语言基础知识,掌握基本语法和常用函数的使用。
•阅读相关教材或参加培训班,了解考试的题型和考察重点。
•多做练习题,加深对知识的理解和应用能力。
•参加模拟考试,熟悉考试流程和时间管理。
•注意复习重点和易错点,做好知识的巩固和回顾。
5. 考试技巧为了提高全国计算机等级考试二级C语言的成绩,考生可以采取以下策略:•注意审题,理解题目的要求和限制条件。
•合理安排时间,控制答题进度。
•多思考,多分析,遇到难题可以尝试从不同角度考虑解决方案。
•注意代码的规范性和可读性,写清楚注释。
•注意错误的处理,避免程序崩溃或出现逻辑错误。
•检查答案,确保没有遗漏语法错误。
c语言函数指针数组在C语言中,函数指针数组是指一个数组中存放多个函数指针的集合。
通过函数指针数组,我们可以在程序运行过程中动态地选择不同的函数进行调用。
函数指针数组的定义格式如下:```返回类型(*函数指针数组名[大小])(参数列表);```其中,返回类型是指函数返回值的类型,函数指针数组名是数组的名称,大小表示函数指针数组中元素的数量,参数列表表示函数的参数类型。
下面我们通过一个示例来说明函数指针数组的用法。
假设我们有一个需求,需要根据用户输入的命令来执行对应的函数。
我们可以先定义一个包含不同函数指针的函数指针数组,然后根据用户输入的命令在数组中查找对应的函数指针,最后调用该函数指针。
首先,我们定义几个需要执行的函数:```cint add(int a, int b)return a + b;int subtract(int a, int b)return a - b;int multiply(int a, int b)return a * b;int divide(int a, int b)return a / b;```然后,我们定义一个函数指针数组,将上述函数指针存入数组中:```cint (*operation[4])(int, int) = {add, subtract, multiply, divide};```接下来,我们编写一个函数来根据用户输入的命令执行相应的函数:```cvoid executeOperation(int operationIndex, int a, int b)if (operationIndex >= 0 && operationIndex < 4)int result = operation[operationIndex](a, b);printf("Result: %d\n", result);} elseprintf("Invalid operation index\n");}```最后,在主函数中获取用户输入的命令,并根据命令调用对应的函数:```cint maiint operationIndex, a, b;printf("Enter operation index (0 for add, 1 for subtract, 2 for multiply, 3 for divide): ");scanf("%d", &operationIndex);printf("Enter two numbers: ");scanf("%d %d", &a, &b);executeOperation(operationIndex, a, b);return 0;```通过以上代码,我们可以根据用户输入的命令选择对应的函数进行调用,并返回相应的结果。
重庆计算机二级c语言知识点总结重庆计算机二级C语言知识点总结一、C语言基础知识1. C语言的概念和特点- C语言是一种通用的高级编程语言,具有简洁的语法和强大的表达能力。
- C语言能够直接操作内存,对硬件进行底层控制,具有高效的性能。
- C语言具有丰富的标准库,可以方便地进行文件操作、字符串处理等任务。
2. C语言的基本语法- 变量和常量的定义和使用。
- 运算符和表达式的使用。
- 控制语句(if、switch、for、while等)的使用。
- 函数的定义和使用。
3. C语言的数据类型- 基本数据类型(int、float、char等):用于表示整数、浮点数和字符。
- 指针类型:用于表示内存地址。
- 数组类型:用于表示一组相同类型的数据。
- 结构体类型:用于表示一个复合的数据结构。
- 枚举类型:用于表示一组离散的值。
4. C语言的输入和输出- 标准输入函数(scanf):用于从键盘读取输入数据。
- 标准输出函数(printf):用于向屏幕输出结果。
5. C语言的内存管理- 内存的分配和释放:使用malloc和free函数进行动态内存分配和释放。
- 内存的访问和操作:使用指针对内存地址进行读写操作。
二、C语言高级特性1. 指针和内存管理- 指针的概念和用法:指针是内存地址的表示,可以用于访问和操作内存。
- 指针的运算和应用:指针可以进行算术运算,并用于实现数据结构和算法。
2. 结构体和联合体- 结构体的定义和使用:结构体是一种复合的数据类型,可以包含多个不同类型的成员变量。
- 结构体的嵌套和引用:结构体可以嵌套定义和引用,用于表示更复杂的数据结构。
- 联合体的定义和使用:联合体是一种特殊的结构体,可以共享存储空间。
3. 指针和函数- 函数指针的定义和使用:函数指针可以指向函数,并用于实现回调函数等功能。
- 指针作为函数参数:可以使用指针作为函数参数,实现对变量的引用传递。
4. 动态内存管理- 动态内存分配和释放:使用malloc、calloc和realloc函数进行动态内存分配,使用free函数进行内存释放。
全国计算机二级考试C语言(最全复习资料)全国计算机二级考试C语言(最全复习资料)C 语言,是一种通用的高级计算机编程语言,广泛应用于软件开发和系统编程。
而全国计算机二级考试则是衡量个人计算机应用能力的重要考试之一。
对于考生来说,准备充分的复习资料是非常重要的。
在这篇文章中,我将为大家提供最全面的 C 语言复习资料,帮助考生更好地备战全国计算机二级考试。
一、基础知识1. C 语言简介:C 语言的历史背景,应用领域等。
2. C 语言的基本语法:变量、数据类型、运算符、控制语句等。
3. 输入和输出:scanf、printf等输入输出函数的使用方法。
4. 数组和字符串:一维数组、多维数组、字符串处理等。
二、函数与指针1. 函数的定义和调用:函数的作用与优势,函数的定义、声明和调用方法。
2. 函数参数传递:值传递和引用传递,指针作为函数参数的使用。
3. 指针的概念和基本操作:指针的定义与初始化,指针的运算,指针与数组的关系等。
4. 动态内存分配:malloc、free等动态内存管理函数的使用方法。
三、结构体与文件操作1. 结构体的定义和使用:结构体的成员变量、结构体数组等。
2. 文件的读写操作:文件的打开、读写与关闭,文件指针的移动等。
3. 文件的顺序读写和随机读写:顺序读写和随机读写的区别与应用。
4. 文件的二进制读写和文本读写:二进制文件和文本文件的区别与使用方法。
四、高级特性1. 位运算:位运算符的使用,位运算在计算机中的应用。
2. 内存管理:静态存储、自动存储、动态存储的概念与区别。
3. 结构体与共用体:结构体和共用体的定义与使用,二者之间的区别。
4. 预处理器:宏定义、条件编译等预处理器的基本概念与使用方法。
五、实践应用1. 综合练习:包括通过 C 语言实现常见算法和数据结构等综合练习题。
2. 项目开发:参与一个小型项目开发,锻炼实际编程能力。
以上是全国计算机二级考试C语言复习资料的基本框架。
考生可以根据自己的实际情况进行针对性的学习和练习。
二级公共基础知识作为必考内容出现,出题形式为选择题前10道,占考试总分的10%。
考试其它比重:1、C语言程序的结构占总分1%2、数据类型及其运算占总分4%3、选择结构程序设计占比分的3%4、循环结构占比分的5%5、数组的定义和引用占比分的5%6、函数占比分的5%7、编译预处理占比分1%8、指针占比分的5%9、结构体占比分的3%10、位运算占比分的2%11、文件操作占比分的2%考试方式上机考试,时长120分钟单选题40分(含公共基础10分),操作题60分(包括程序填空题、程序修改题、程序设计题)第一部分 C语言知识复习资料第一章C语言基本知识(90分)【考点1】C程序用C语言编写的程序称为C语言源程序,源程序文件的后缀名为“.c”。
源程序经编译后生成后缀名为“.obj”的目标文件,再把目标文件与各种库函数连接起来,生成“.exe”可执行文件。
C语言有三种基本结构:顺序结构、选择结构、循环结构。
【考点2】main函数又称主函数,是C程序的入口。
main后面跟一对小括号和一对花括号,花括号括起来的部分称为main 函数的函数体。
一个C程序从main函数开始执行,到main函数体执行完结束,而不论main函数在整个程序中的位置如何。
每一个程序有且仅有一个main函数,其他函数都是为main函数服务的。
【考点3】存储形式计算机在电脑中保存数据是采用二进制形式,由0或1构成的二进制称为位(bit),八个位构成一个字节(Byte),1个Byte=8个bit。
二进制、八进制、十六进制转化为十进制采用乘法,十进制转化为二进制、八进制、十六进制采用除法。
数据的存放位置就是它的地址。
【考点4】注释是对程序的说明,可出现在程序中任意合适的地方,注释从“/*”开始到最近一个“*/”结束,其间任何内容都不会被计算机执行,注释不可以嵌套。
【考点5】书写格式每条语句的后面必须有一个分号,分号是语句的一部分。
一行内可写多条语句,一个语句可写在多行上。
全国计算机二级:C语言之指针、数组和函数
基本解释
1、指针的本质是一个与地址相关的复合类型,它的值是数据存放的位置(地址);数组的本质则是一系列的变量。
2、数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变。
指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来操作动态内存。
3、当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。
问题:指针与数组
听说char a[]与char *a是一致的,是不是这样呢?
答案与分析:
指针和数组存在着一些本质的区别。
当然,在某种情况下,比如数组作为函数的参数进行传递时,由于该数组自动退化为同类型的指针,所以在函数内部,作为函数参数传递进来的指针与数组确实具有一定的一致性,但这只是一种比较特殊的情况而已,在本质上,两者是有区别的。
请看以下的例子:
char a[] = "Hi, pig!";
char *p = "Hi, pig!";
上述两个变量的内存布局分别如下:
数组a需要在内存中占用8个字节的空间,这段内存区通过名字a来标志。
指针p则需要4个字节的空间来存放地址,这4个字节用名字p来标志。
其中存放的地址几乎可以指向任何地方,也可以哪里都不指,即空指针。
目前这个p指向某地连续的8个字节,即字符串“Hi, pig!”。
另外,例如:对于a[2]和p[2],二者都返回字符‘i’,但是编译器产生的执行代码却不一样。
对于a[2],执行代码是从a的位置开始,向后移动2两个字节,然后取出其中的字符。
对于p[2],执行代码是从p的位置取出一个地址,在其上加2,然后取出对应内存中的字符。
问题:数组指针
为什么在有些时候我们需要定义指向数组而不是指向数组元素的指针?如何定义?
答案与分析:
使用指针,目的是用来保存某个元素的地址,从而来利用指针独有的优点,那么在元素需要是数组的情况下,就理所当然要用到指向数组的指针,比如在高维需要动态生成情况下的多维数组。
定义例子如下: int (*pElement)[2]。
下面是一个例子:
int array[2][3] = {{1,2,3},{4,5,6}};
int (*pa)[3]; //定义一个指向数组的指针
pa = &array[0]; // '&'符号能够体现pa的含义,表示是指向数组的指针
printf ("%d", (*pa)[0]); //将打印array[0][0],即1
pa++; // 猜一猜,它指向谁?array[1]?对了!
printf ("%d", (*pa)[0]); // 将打印array[1][0],即4
上述这个例子充分说明了数组指针—一种指向整个数组的指针的定义和使用。
需要说明的是,按照我们在第四篇讨论过的,指针的步进是参照其所指对象的大小的,因此,pa++将整个向后移动一个数组的尺寸,而不是仅仅向后移动一个数组元素的尺寸。
问题:指针数组
有如下定义:
struct UT_TEST_STRUCT *pTo[2][MAX_NUM];
请分析这个定义的意义,并尝试说明这样的定义可能有哪些好处?
答案与分析:
前面我们谈了数组指针,现在又提到了指针数组,两者形式很相似,那么,如何区分两者的定义呢?分析如下:
数组指针是:指向数组的指针,比如 int (*pA)[5]。
指针数组是:指针构成的数组,比如int *pA[5]。
至于上述指针数组的好处,大致有如下两个很普遍的原因:
a)、各个指针内容可以按需要动态生成,避免了空间浪费。
b)、各个指针呈数组形式排列,索引起来非常方便。
在实际编程中,选择使用指针数组大多都是想要获得如上两个好处。
问题:指向指针的指针
在做一个文本处理程序的时候,有这样一个问题:什么样的数据结构适合于按行存储文本?
答案与分析:
首先,我们来分析文本的特点,文本的主要特征是具有很强的动态性,一行文本的字符个数或多或少不确定,整个文本所拥有的文本行数也是不确定的。
这样的特征决定了用固定的二维数组存放文本行必然限制多多,缺乏灵活性。
这种场合,使用指向指针的指针有很大的优越性。
现实中我们尝试用动态二维数组(本质就是指向指针的指针)来解决此问题:
图示是一个指针数组。
所谓动态性指横向(对应每行文本的字符个数)和纵向(对应整个文本的行数)两个方向都可以变化。
就横向而言,因为指针的灵活性,它可以指向随意大小的字符数组,实现了横向动态性。
就竖向而言,可以动态生成及扩展需要的指针数组的大小。
下面的代码演示了这种动态数组的用途:
// 用于从文件中读取以 '\0'结尾的字符串的函数
extern char *getline(FILE *pFile);
FILE *pFile;
char **ppText = NULL; // 二维动态数组指针
char *pCurrText = NULL; // 指向当前输入字符串的指针
ULONG ulCurrLines = 0;
ULONG ulAllocedLines = 0;
while (p = getline(pFile))
{
if (ulCurrLines >= ulAllocedLines)
{
// * 当前竖向空间已经不够了,通过realloc对其进行扩展。
ulAllocedLines += 50; // 每次扩展50行。
ppText = realloc (ppText, ulAllocedLines * (char *));
if (NULL == ppText)
{
return; // 内存分配失败,返回
}
}
ppText[ulCurrLines++] = p; // 横向“扩展”,指向不定长字符串
}
问题:指针数组与数组指针与指向指针的指针
指针和数组分别有如下的特征:
指针:动态分配,初始空间小
数组:索引方便,初始空间大
下面使用高维数组来说明指针数组、数组指针、指向指针的指针各自的适合场合。
多维静态数组:各维均确定,适用于整体空间需求不大的场合,此结构可方便索引,例a[10][40]。
数组指针:低维确定,高维需要动态生成的场合,例a[x][40]。
指针数组:高维确定,低维需要动态生成的场合,例a[10][y]。
指向指针的指针:高、低维均需要动态生成的场合,例a[x][y]。
问题:数组名相关问题
假设有一个整数数组a,a和&a的区别是什么?
答案与分析:
a == &a == &a[0],数组名a不占用存储空间。
需要引用数组(非字符串)首地址的地方,我一般使用&a[0],使用a容易和指针混淆,使用&a容易和非指针变量混淆。
区别在于二者的类型。
对数组a的直接引用将产生一个指向数组第一个元素的指针,而&a的结果则产生一个指向全部数组的指针。
例如:
int a[2] = {1, 2};
int *p = 0;
p = a; /* p指向a[0]所在的地方 */
x = *p; /* x = a[0] = 1*/
p = &a; /* 编译器会提示你错误,*/
/*显示整数指针与整数数组指针不一样 */
问题:函数指针与指针函数
请问:如下定义是什么意思:
int *pF1();
int (*pF2)();
答案与分析:
首先清楚它们的定义:
指针函数,返回一个指针的函数。
函数指针,指向一个函数的指针。
可知:
pF1是一个指针函数,它返回一个指向int型数据的指针。
pF2是一个函数指针,它指向一个参数为空的函数,这个函数返回一个整数。