第二部分二级C 语言程序设计
值)增1、减1 所“跨越”的字节数是不同的。因此定义指针变量时必须区分基类型;基类型不同的指针变量不能混合使用。 考点2 指针变量的操作 1.给指针变量赋地址值
给指针变量赋地址值的方式有3种方式....: (1)通过求地址运算符(&)获得地址值 通过单目运算符(&)求出运算对象的地址,把这个地址赋给指针变量。 (2)通过指针变量获得地址值
可以通过赋值运算,把一个指针变量中的地址值赋给另一个指针变量,从而使这两个指针指向同一地址。
(3)通过标准函数获得地址值
可以通过调用库函数malloc 和calloc 在内存中开辟动态存储单元,并把所开辟的动态存储单元的地址赋给指针变量。 2.给指针变量赋“空”值
NULL 是在stdio.h 头文件中定义的预定义符。 NULL的代码值为0。可以给指针变量赋NULL 值。 3.对指针变量的操作
(1)通过指针来引用一个存储单元
C语言提供了一个间接访问运算符(*),又称间址运算符,它是一个单目运算符。
当指针变量中存放了一个确切的地址值 时,就可以用“间接访问运算符”通过指针来引用该地址的存储单元。 (2)移动指针
移动指针:是对指针变量加上或减去一个整数,或通过赋值运算,使指针变量指向相邻的存储单元。因此,只有当指针指向一串连续的存储单元时,指针的移动才有意义。
当指针指向一串连续的存储单元时,可以对指针变量进行加上或减去一个整数的运算,也可以对指向同一串连续存储单元的两个指针进行相减的运算。除此之外,不可以对指针进行任何其他的算术运算。 (3)指针比较
在关系表达式中可以对两个指针进行比较。 考点3 函数之间地址的传递
1.形参为指针变量时实参和形参之间的数据传递
若函数的形参为指针类型,调用该函数 时,对应的实参必须是基类型相同的地址值或
者是已指向某个存储单元的指针变量。 2.通过传送地址值改变变量值
通过传送地址值,可以在被调用函数中对调用函数中的变量进行引用,利用此种形式可以把两个或两个以上的数据从被调用函数返回到调用函数。
3.函数返回地址值
定义函数的类型为指针类型,这时函数返回地址值。注意:函数定义时“*”的位置。
第7 章数组
考点1 一维数组的定义及元素的引用 1.一维数组的定义
当数组中每个元素只带有一个下标时,称这样的数组为一维数组。
【格式】类型说明符数组名[整型常量表达式],??;
2.一维数组的初始化
当系统为所定义的数组在内存中开辟一串连续的存储单元时,这些存储单元中并没有确定的值,可以在定义语句中为所定义数组的各个元素赋初值。在给一维数组赋值时应注意 7个方面....:所赋初值放在等号后的一对花括号中;数值类型必须与所说明的类型一致;所赋 初值之间用逗号隔开;系统将按这些数值的排列顺序;在指定初值时,第一个初值必定赋给下标为0 的元素,因此,不可能跳过前面的元素给后面的元素赋初值;当所赋初值少于所定义数组的元素个数时,将自动给后面的元素补初值0。对于字符数组也同样补以初值0(即 '\\0');当所赋初值多于所定义数组的元素个数时,在编译时将给出出错信息。 3.通过赋初值定义数组的大小
C 语言规定可以通过赋初值来定义数组的大小,这时数组说明符的一对方括号中可以不指定数组的大小。 4.一维数组和指针
(1)一维数组和数组元素的地址
① 数组首地址。在函数体中或在函数外部定义的数组名可以认为是一个存放地址值的指针变量名。其中,数组的地址值是数组第一个元素的地址,也就是数组所占一串连续存储单元的起始地址,定义数组时的类型即是此指针变量的基类型。② 数组元素地址的表示方式。可以对数组名加一个整数的办法,来依
- 24 -
选择题考点秘籍—二级C 语言
次表达该数组中不同的元素的地址。
(2)通过数组元素的地址引用数组元素对于一维整型数组a[]的定义语句:int
a[8]={0,1,2,3,4,5,6,7},可通过a[0],a[1],a[2], a[3],a[4],a[5],a[6],a[7],来引用数组a[ ]中的每一个元素。
(3)通过指针引用一维数组元素,若有定 义语句“floata[10],*p,k;”,执行语句“p=a;”或“p= &a[0];”后,则p 指向了a 数组的首地址,因此,可以使用“间接访问运算符”,通过指针变量p 来引用a 数组中的元素。 考点2 函数对一维数组及元素的引用 1.数组元素做实参
当调用函数时,数组元素可以作为实参传送给形参,每个数组元素实际上代表内存中的一个存储单元,因此与普通变量一样,对应的形参必须是类型相同的变量。数组元素的值可以传送给该变量,在函数中只能对该变量进行操作,而不能直接引用对应的数组元素,更不能在函数中改变对应数组元素中的值。 2.数组名做实参
数组名也可以作为实参传递,但数组名本身是一个地址值,因此,对应的形参就应当是一个指针变量,此指针变量的基类型必须与数组的类型一致。在函数中,可以通过指针变量来引用调用函数中对应的数组元素,从而达到改变调用函数中对应数组元素的值。当传送数组名时,在被调用函数中也同样可用数组元素的形式来引用调用函数中对应的数组元组。 3.数组元素地址作为实参
当用数组元素地址作为实参时,因为是地址值,所以对应的形参也应当是基类型相同的指针变量。在这段程序中,函数sum 的形式参数为整形指针变量a,在主函数的for 循环语句中,把实参数组aa 的元素地址值&aa[i]传递给形参a。 4.函数指针形参和函数体中数组的区别
若有以下程序,程序中定义了fun 函数,形参a 指向主函数中的w 数组,函数体内定义了一个b 数组,函数把b 数组的起始地址作为函数值返回,企图使主函数中的指针p 指向函数体内b 数组的开头。 考点3 二维数组的定义 1.二维数组的定义
当数组中每个元素带有两个下标时,称这
样的数组为二维数组。在逻辑上可以把二维数组看成是一个具有行和列的表格或一个矩阵。
在C 语言中,二维数组定义语句形式如下: 【格式】类型名数组名[常量表达式1][常量表达式2],??;
2.二维数组的初始化
初始化二位数组时应注意4点要求:①所赋初....
值个数与数组元素的个数相同。② 每行所赋初值 个数与数组元素的个数可以不同。③ 所赋初值行数少于数组行数。④ 赋初值时省略的花括号对。在给二维数组赋初值时可以不用行花括号对。 3.通过赋初值定义二维数组的大小
对于二维数组通过所赋初值的个数来确定数组的大小。在这种情况下,只可以省略第一个方括号中的常量表达式,而不能省略第二个方括号中的常量表达式。 考点4 二维数组和指针
1.二维数组和数组元素的地址
(1)二维数组a 由若干个一维数组组成在C 语言中定义的二维数组实际上是一个 一维数组,这个一维数组的每个元素又是一个 一维数组。
(2)二维数组名也是地址值常量
二维数组名同样也是一个存放地址常量的指针,其值为二维数组中第一个元素的地址。以前面的数组a 为例,数组名a 的值与a[0]的值相同,只是其基类型为具有4 个整型元素的数组类型。二维数组名应理解为一个行指针。即a+0 的值与 a[0]的值相同,a+1 的值与a[1]的值相同,a+2 的值与a[2]的值相同。它们分别代表a 数组中第1、第2、第3 行的首地址。在表达式a+1 中,数值1 ...的单位应当是4×2 个字节,而不是2 个字节。 ..
(3)二维数组元素的地址
二维数组元素的地址可以由表达式&a[i][j] 求得,也可以通过每行的首地址来表示。以上二维数组a 中,每个元素的地址可以通过每行的首地址a[0]、a[1]、a[2]等来表示。 2.通过地址引用二维数组
若有以下定义:int a[3][4],i,j;,且0≤i<3、0≤j<4,则a 数组元素可用以下5种表达式来 .....引用。
【表达1】a[i][j] 【表达2】*(a[i]+j) 【表达3】*(*(a+i)+j)
- 25 -
第二部分二级C 语言程序设计
【表达4】(*(a+i))[j]
【表达5】*(&a[0][0]+4*i+j)
引用数组元素时应注意几点:①在表达式 2 的表达式*(a[i]+j)中,因为a[i]的基类型为int, j 的位移量为2×j 字节;②在表达式3 的表达式*(*(a+i)+j)中,a的基类型为4个元素的数组, i 的位移量为4×2×i 字节,而*(a+i)的基类型 为int,j 的位移量为2×j 字节;③在表达式4 中,*(a+i)外的一对圆括号不可少;④在表达式5 中,&a[0][0]+4*i+j 代表了数组元素a[i][j] 的地址,通过间址运算符(*)号,表达式 *(&a[0][0]+ 4*i+j)代表了数组元素a[i][j]的存储单元。
3.通过建立一个指针数组引用二维数组元素
若有以下定义:int *p[3],a[3][2],i,j;
说明符*p[3]中,遵循运算符的优先级,一对“[ ]”的优先级高于“*”号,因此p 首先与[ ]结合,构成p[3],说明p 是一个数组名,系统将为它开辟3 个连续的存储单元;
在它前面的星号(*)是说明数组p 是指针类型,它的每个元素都是基类型为int 的指针。若满足条件0≤i<3,是p[i]和a[i]的基类型相同,p[i]=a[i]是合法的赋值表达式。
考点5 二维数组名和指针数组作为实参
当二维组名作为实参时,对应的形参必须是一个行指针变量。
当指针数组名作为实参时,对应的形参应当是一个指向指针的指针。
第8 章字符串
考点1 用一维字符数组存放字符串 1.用一维字符数组存放字符串 (1)表示字符串常量的约定
字符串常量是由双引号括起来的一串字符,在表示字符串常量时,不需要人为在其末尾加入'\\0',C 编译程序将自动完成这一工作,在末尾添加字符'\\0'。
(2)字符串常量给出地址值
字符串常量被隐含处理成一个以'\\0'结尾的无名字符型一维数组。字串符常量是字符串在内存中所占的一串连续存储单元(即无名一维字符数组)的首地址。 2.用一维数组存放字符串
(1)通过赋初值的方式给一维字符数组赋字符串
① 用给一般数组赋初值的相同方式给一 维字符数组赋初值。② 在赋初值时直接赋字.....
符串常量。可以直接用字符串常量给一维字符 数组赋初值,系统将按字符串中实际的字符个数来定义数组的大小。
(2)在C 程序执行过程中给一维字符数组赋字符串
① 不可以用赋值语句给字符数组整体赋一串字符。② 给数组元素逐个赋字符值,最后人为加入串结束标志在程序执行过程中,可 以通过逐个给数组元素赋值的方式,达到给一维字符数组赋字符串的目的。 考点2 使指针指向字符串
要使指针指向字符串,可以通过以下两种形式来实现。
(1)通过赋初值的方式使指针指向字符串在定义字符指针变量的同时,将存放字符 串的存储单元起始地址赋给指针变量。
(2)通过赋值运算使指针指向一个字符串如果已经定义了一个字符型指针变量,可 以通过赋值运算符将某个字符串的起始地址 赋给它,从而使其指向一个具体的字符串。 考点3 字符串的输入和输出
1.输入和输出字符串时的必要条件
输入和输出字符串时有3个必要条件......:① 当对字符串进行输出时,输出项既可以是字符 串常量或字符数组名,也可以是已指向字符串的字符指针变量;② 当对字符串进行输入时,输入项可以是字符数组名,也可以是字符指针变量。当用字符数组名作为输入项时,输入的字符串将存放在字符数组中,因此,字符数组应有足够的存储空间;③ 当使用指针变量作为输入项时,指针必须已经指向确切的、足够大 ..
的存储空间,以便使输入的字符串能存放在其 所指的具体的内存单元中。
2.用格式说明符%s 进行整串输入和输出 (1)在scanf 函数中使用格式说明符%s 实现整体输入字符串
【格式】scanf(\
【说明】“str_adr”是地址值。调用此函数时,输入字符依次放入以这一地址为起点的存储单元中,并自动在末尾加'\\0'。
(2)在printf 函数中使用格式说明符%s 实现整体输出字符串
- 26 -
选择题考点秘籍—二级C 语言
【格式】printf(\
【说明】“str_adr”是地址值。调用printf 函数时,将从这一地址开始,依次输出存储单元中的字符,直到遇第一个'\\0'为止。'\\0'是结束标志,不在输出字符之列。输出结束后不自动换行。3.调用gets、puts 函数在终端输入或输出一 行字符串 (1) gets函数
【格式】gets(str_adr); 【说明】“str_adr”是存储放字符串的起始地址,可以是字符数组名、字符数组元素的地址或字符指针变量。gets 函数用来从终端键盘读入字符串(包括空格符),直到读入一个换. 行符为止。换行符读入后,不作为字符串的内..
容,系统将自动用'\\0'代替。 (2) puts 函数
【格式】puts(str_adr);
【说明】str_adr 是存放待输出字符串的起始地址。调用puts 函数时,将从这一地址开始,依次输出存储单元中的字符,当遇到第一个'\\0'时结束输出,并自动输出一个换行符。 考点4 字符串数组
所谓字符串数组就是数组中的每个元素又都是一个存放字符串的一维数组。实现这一数据结构有3种形式....:① 由于一个二维数组 可以看作是一个一维数组,这个一维数组中的 每一个元素又是一个一维数组。所以可以将一个二维字符数组视为一个字符串数组。二维字符数组的第一个下标决定了字符串的个数,第二下标决定了字符串的最大长度;② 字符串数组也可以定义的同时赋初值;③ 可以定义字符型指针数组并通过赋初值来构成一个类似的字符串数组。
考点5 用于字符串处理的函数
1.字符串复制(拷贝)函数strcpy
字符串复制(拷贝)函数strcpy。 【格式】strcpy(s1,s2);
【说明】该函数用来把s2 所指字符串(源)的内容复制到s1 所指存储空间(目的)中,函数返回s1 的值,即目的串的首地址。s1 必须指向一个足够容纳s2 串的存储空间。 2.字符串连接函数strcat
字符串连接函数strcat。 【格式】strcat(s1,s2);
【说明】函数将s2 所指字符中的内容连接到 s1 所指的字符串后面,并自动覆盖s1 串末尾的'\\0',函数返回s1 所指的地址值。s1 所指字符串应有足够的空间容纳两串合并的内容。 3.求字符串长度函数strlen
求字符串长度函数strlen。 【格式】strlen(s);
【说明】strlen 函数计算出以s 为起始地址的字符串长度,并作为函数值返回。这一长度不包括串尾的结束标志'\\0'。 4.字符串比较函数strcmp
字符串比较函数strcmp。 【格式】strcmp(s1,s2);
【说明】该函数用来比较s1和s2所指字符串的大小。若s1>s2,则函数值大于0(正数);若s1=s2,则函数值等于0;若s1 第9 章编译预处理和动态存储分配 考点1 编译预处理 在C 语言中,凡是以“#”号开头的行,都称为“编译预处理”命令行。所谓编译预处理就是在C 编译程序对源程序进行编译前,由 .编译预处理程序对这些编译预处理命令行进 行处理的过程。C语言有12预处理命令: ..种...... #define、#undef、#include、#if、#else、#elif、 #endif、#ifdef、#ifndef、#line、#pragma;#error。 考点2 宏替换 1.不带参数的宏定义 (1)定义不带参数的宏 【格式】#define 宏名替换文本或 #define 宏名 【说明】在define、宏名和替换文本之间用空格隔开;#define 命令行可以不包含“替换文本”,这仅说明标识符“被定义”。 (2)使用不带参数的宏时应注意7个事项....: ①替换文本中可以包含已定义过的宏名;②当 宏定义在一行中写不下,需要在下一行继续时,只需在最后一个字符后紧接着一个反斜线“\\”; ③ 同一个宏名不能重复定义,除非两个宏定义命令行完全一致;④ 替换文本不能替换双括号 中与宏名相同的字符串;⑤ 替换文本并不替换用户标识符中的成分;⑥ 用作宏名的标识符通常用大写字母表示,这并不是语法规定,只是 一种习惯,以便与程序中的其他标识符相区别; - 27 - 第二部分二级C 语言程序设计 【格式】malloc(size) ⑦ 在C 程序中,宏定义的定义位置一般写在程 【说明】size 的类型为unsigned int。malloc 序的开头。 函数用来分配size 个字节的存储区,返回一个2.带参数的宏定义 指向存储区首地址的基类型为void 的地址。若(1)定义带参数的宏: 【格式】#define 宏名(形参表) 替换文本 没有足够的内存单元供分配,函数返回空 (NULL)。 【说明】例如,#defineMU(X,Y)((X)*(Y))。 (2) free函数 在这个宏定义命令中,MU(X,Y)简称为 释放已分配的块。 “宏”,其中MU是一个用户标识符,称为宏 【格式】void free(void *ptr); 名,宏名和左括号“(”必须紧挨着,它们之间.. 2.calloc 函数 不得留有空格。其后一对圆括号中由若干称为 ANSIC 标准规定calloc 函数返回值的类型形参的标识符组成,各形参之间用逗号隔开。 为void*。 “替换文本”中通常应该包含形参。 【格式】calloc(n,size) (2)使用带参数的宏时应注意6个事项:① 和.... 【说明】n 和size 的类型都为unsigned int。 不带参数的宏名相同,同一个宏名不能重复 calloc 函数用来给n 个同一类型的数据项分配连定义,除非两个宏定义命令行完全一致;② 在 续的存储空间,每个数据项的长度为size 个字调用带参数的宏名时,一对圆括号必不可少, 节。若分配成功,函数返回存储空间的首地址;圆括号中实参的个数应该与形参个数相同,若 否则返回空。通过调用calloc 函数所分配的存储有多个参数,它们之间用逗号隔开。在预编译 单元,系统自动置初值0。 时,编译预处理程序用“替换文本”来替换宏, 第10 章结构体、共用体和用户定义类型 并用对应的实参来替换“替换文本”中的形参; ③ “替换文本”的形参和整个表达式应该用括号考点1 结构体 括起来;④ 在宏替换中对参数没有类型的要求;1.用typedef 说明一个新类型 C 语言允许用typedef 说明一种新类型名。 ⑤宏替换是在编译前由预处理程序完成的,因此 【格式】typedef 类型名标识符; 宏替换不占运行的时间;⑥ 宏替换中,实参不能 【说明】“类型名”必须是在此语句之前替换括在双引号中的形参。 已定义的类型标识符;“标识符”是一个用户3.终止宏定义 定义标识符,用作新的类型名;typedef 语句的用#undefine 提前终止宏定义的作用域。 作用仅仅是用“标识符”来代表已存在的“类考点3 文件包含处理 型名”,并未产生新的数据类型,原有类型名依 文件包含是指在一个文件中,去包含另 然有效。 一个文件的全部内容。C 语言用#include 命令 2.结构体类型数据的定义 行来实现文件包含的功能。 struct 结构体标识名 #include \文件名\或#include <文件名> {类型名1结构成员表1; 【说明】在预编译时,预编译程序将用指 类型名2 结构成员表2; 定文件中的内容来替换此命令行。如果文件名 …型名n结构成员表n;}; 用双引号括起来,系统先在源程序所在的目录 【说明】struct 是关键字,是结构体类型的内查找指定的包含文件,如果找不到,再按照 标志。“结构体标识名”和“结构成员名”都是用户系统指定的标准方式到有关目录中去寻找;如 定义的标识符,“结构体标识符”是可选项,在说果文件名用尖括号括起来,系统将直接按照系 明中可以不出现。每个“结构成员表”中都可以统指定的标准方式到有关目录中去寻找。 含有多个同类型的成员名,它们之间用逗号分隔。 考点4 动态存储分配 结构体中的成员名和程序中的其他变量可以同名; 1.malloc 函数和free 函数 不同结构体中的成员也可以同名。注意:结构体 (1) malloc函数 说明要以分号“;”结尾。 ANSIC 标准规定malloc 函数返回值的类型为void*。 - 28 -