文章教程

全国计算机等级考试二级C语言10.1宏定义

8/22/2020 10:24:52 PM 人评论 次浏览

10.1 宏定义

考点1 不带参数的宏定义

真考链接

此知识点简单,属于重点理解重点掌握知识点。该知识点在选择题中的考核概率为60%。

不带参数的宏定义命令行形式如下:

#define宏名 替换文本 或 #define宏名

在define宏名和宏替换文本之间要用空格隔开。

说明:宏名一般习惯用大写字母表示,宏替换的过程实质上是原样替换的过程。宏定义可以减少程序中重复输写某些字符串的工作量。

注意:可以用 #undef命令终止宏定义的作用域。

例如:

#define PI 3.14   -

main()    ↑

{    PI的作用域

}    ↓

#undef PI    -

在进行宏定义时,可以引用已定义的宏名,例如:

#define R 15.5

#define PI 3.14

#define L 2*PI*R

小提示

使用宏定义过的常量,只要在定义常量处改变常量的值,则此常量在整个程序中的值都换成最新的值。

宏定义是用宏名代替一个字符串,也就是作简单的置换,不作语法检查。宏定义不是 C语句,不必在行末加分号。

#define命令出现在程序中函数的外面,宏名的有效范围为定义命令之后到本源文件结束可以用#undef命令终止宏定义的作用域。

真题精选

【例1】以下函数的功能是,通过键盘输入数据,为数组中的所有元素赋值。 在下划线处应填入的是(  )

#define N 10

void arrin(int x[N])

{ int i=0;while(i<N)

scanf("% d",______);

A.x+i    B.&x[i+1]    C.x+(i++)    D.&x[ ++i]

【答案】C

【解析】本题考查了宏替换的知识,同时考查了自加的知识,因为要通过键盘输入数据,为数组中的所有元素赋值,所以下标要从0开始到9,只有选项C可以满足。

【例2】下面是对宏定义的描述,不正确的是(  )

A.宏不存在类型问题,宏名无类型,它的参数也无类型

B.宏替换不占用运行时间

C.宏替换时先求出实参表达式的值,然后代入形参运算求值

D.其实,宏替换只不过是字符替代而已

【答案】C

【解析】本例涉及宏替换的基本概念及与函数的简单比较,题目中的选项也确实是需要了解的一般知识。在本例中,宏替换的实质恰如选项D所言,是字符替代,因此,不会有什么类型,当然,就更不可能进行计算(C错误)。带参数的宏与函数相比,宏在程序编译之前已经将代码替换到程序内,执行时不会产生类似于函数调用的问题,可以说不占运行时间。

考点2 带参数的宏定义

真考链接

此知识点简单,属重点理解重点掌握内容。该知识点在选择题中的考核概率为70%。

定义的一般形式为:

#define宏名(参数表)字符串。

宏定义不只进行简单的字符串替换,还要进行参数替换,例如:

#define MV(x,y)((x)*(y))

a=MV(5,2);/* 引用带参数的宏名 */

b=6/MV(a+3,a);

以上宏定义命令行中,MV(x,y)称为“宏”,其中 MV是一个用户标识符,称为宏名。宏名和左括号“(”必须紧挨着,它们之间不能留有空格,其后圆括号中由称为形参的标识符组成,并且可以有多个形参,各参数之间用逗号隔开,“替换文本”中通常应该包含有形参。

执行过程:如果程序中有带实参的宏,则按#define命令行中指定的字符串从左到右进行替换。如果字符串中包含宏中的形参(如 x,y),则将程序语句中相应的实参(可以是常量、变量或表达式)代替形参。如果宏定义中的字符串中的字符不是参数字符(如(x*y)中的“*”号),则保留。这样就形成了替换的字符串。

带参数的宏和函数之间有一定类似之处,在引用函数时也是在函数右面的括号写实参,也要求实参与形参数目相等,但两者是不同的,主要表现在以下几个方面:

(1)函数调用时,要求实参、形参类型相匹配,但在宏替换中,对参数没有类型的要求。

(2)函数调用时,先求出实参表达式的值,然后代入形参,而使用带参数的宏只是进行简单的字符串替换。

(3)函数调用是在程序运行时处理的,要分配临时的内存单元,还要占用一系列的处理时间。宏替换在编译预处理时完成,因此,宏替换不占运行时间,不被分配内存单元,不进行值的传递,也没有“返回值”的概念。

(4)使用宏的次数较多时,宏展开后源程序变长,而函数调用不会。

小提示

与不带参数的宏定义相同,同一个宏名不能重复定义。在替换带参数的宏名时,圆括号必不可少。

常见问题

带参数的宏与函数有何异同点?

的确,带参数的宏与函数有一定的类似之处,在引用函数时也是在函数名后的括号内写实参,也要求实参与形参的数目相等。但是带参数的宏定义与函数是不同的:①函数调用时,先求出实参表达式的值,然后代入形参。而使用带参数的宏只是进行简单的字符替换。②函数调用是在程序运行时处理的,分配临时的内存单元。而宏展开则是在编译时进行的,在展开时并不分配内存单元,不进行值的传递处理。

真题精选

【例1】有以下程序

#define N 2

#define M N+1

#define NUM(M+1)*M/2

#include <stdio.h>

main()

{ int i;

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

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

for循环执行的次数是(  )。

A.5    B.6    C.8    D.9

【答案】C

【解析】程序中for循环的执行次数取决于NUM的值,因此正确地计算NUM的值是关键。在(M+1)*M/2中替换M替换后为(N+1+1)*N+1/2;,然后替换N为(2+1+1)*2+1/2。这时可以根据其中的数字进行计算,得到4*2+1/2,计算的最后结果是8。

总结:切不可直接把值代入。例如,认为M的值是3,于是认为NUM是(3+1)*3/2,而得出错误的结果6

【例2】以下程序的输出结果为(  )

#include <stdio.h>

#define SQR(x)x*x

main()

int a,k=3;

a= ++SQR(k+1);

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

A.6    B.10    C.8    D.9

【答案】D

【解析】此题程序中定义了一个带参数的宏名为SQR,当程序中遇到此宏名进行展开时,则应使用定义时的字符串x*x进行替换。替换的原则是:遇到形参x,则以实参k+1代替,其他字符不变。所以,SQR(k+1)经宏展开后成为字符串k+1*k+1。整个赋值语句的形式变为a=++k+1*k+1;,k的值为3。若按从左到右的顺序运算,k先自增1,变为4,则a=4+1*4+1=9。

教程类别