C二级 第9章 编译预处理和动态存储分配
1.以下叙述中正确的是()。
A) 在C语言中,预处理命令行都以"#"开头
B) 预处理命令行必须位于C源程序的起始位置
C) #include
D) C语言的预处理不能实现宏定义和条件编译的功能
参考答案:A
【解析】预处理命令是以"#"号开头的命令,它们不是C语言的可执行命令,这些命令应该在函数之外书写,一般在源文件的最前面书写,但不是必须在起始位置书写,所以B),C)错误。C)语言的预处理能够实现宏定义和条件编译等功能,所以D)错误。
2.以下关于宏的叙述中正确的是()。
A) 宏替换没有数据类型限制B) 宏定义必须位于源程序中所有语句之前
C) 宏名必须用大写字母表示D) 宏调用比函数调用耗费时间
参考答案:A
【解析】宏定义写在函数的花括号外边,作用域为其后的程序,通常在文件的最开头,所以B)选项中宏定义必须位于源程序中所有语句之前是错误的。宏名一般用大写,但不是必须用大写,所以C)选项错误。宏展开不占运行时间,只占编译时间,函数调用占运行时间(分配内存、保留现场、值传递、返回值),所以D)选项错误。
3.有以下程序:
#include
#define PT 3.5 ;
#define S(x) PT*x*x ;
main()
{int a=1,b=2;printf("%4.1f\n" ,S(a+b));}
程序运行后的输出结果是()。
A) 7.5 B) 31.5 C) 程序有错无输出结果D) 14.0
参考答案:C
【解析】宏定义不是C语句,末尾不需要有分号。所以语句printf("%4.1f\n" ,S(a+b));展开后为
printf("%4.1f\n" ,3.5;*a+b*a+b;);所以程序会出现语法错误。
4.若程序中有宏定义行:
#define N 100
则以下叙述中正确的是
A) 宏定义行中定义了标识符N的值为整数100
B) 在编译程序对C源程序进行预处理时用100替换标识符N
C) 上述宏定义行实现将100赋给标示符N
D) 在运行时用100替换标识符N
参考答案:B
【解析】本题考查预编译相关知识,宏定义在编译程序时做了一个简单的替换,所以选项B正确。
5.有以下程序
#include
#define N 3
void fun( int a[][N], int b[] )
{ int i, j;
for( i=0; i { b[i] = a[i][0]; for( j=1; j if ( b[i] < a[i][j] ) b[i] = a[i][j]; } } main() { int x[N][N] = {1, 2, 3, 4, 5, 6, 7, 8, 9}, y[N] ,i; fun( x, y ); for ( i=0; i printf( "\n" ); } 程序运行后的输出结果是 A) 3,5,7 B) 1,3,5, C) 2,4,8, D) 3,6,9, 参考答案:D 【解析】函数fun()的作用是求出二维数组a[][N]中每一行中的最大元素,所以在main()函数中执行完fun(x,y)后,数组y中的元素为二维数组x[N][N]每一行的最大元素。因此D选项正确。 6.下列选项中,能正确定义数组的语句是 A) intnum[0...2008]; B) intnum[]; C) int N=2008; D) #define N 2008 intnum[N]; intnum[N]; 参考答案:D 【解析】C语言不允许定义动态数组,定义数组的大小必须为常量表达式。A选项错误,C语言中数组没有此类型的定义方法;B选项错误,定义数组应指明数组大小,如果不指明数组大小,需要给定初值的个数;C选项错误,N为变量,不能用来定义数组大小。因此D选项正确。 7.若要求定义具有10个int型元素的一维数组a,则以下定义语句中错误的是 A) #define n 5 B) int n=10,a[n]; C) int a[5+5];D) #define N 10 int a [2*n]; int a[N]; 参考答案:B 【解析】一维数组的定义方式为:类型说明符数组名[常量表达式];注意定义数组时,元素个数不能是变量。因此应该选B选项。 8.有以下程序 #include #define N 4 void fun(int a[][N], int b[]) { int i; for(i=0;i } main() { int x[][N]={{1,2,3},{4}, {5,6,7,8},{9,10}}, y[N], i; fun(x, y); for (i=0;i printf("\n"); } 程序的运行结果是 A) 1,0,7,0, B) 1,2,3,4, C) 1,4,5,9, D) 3,4,8,10, 参考答案:A 【解析】该程序首先在定义变量时,对二维数组x[][N]进行赋值操作;调用函数fun,函数fun的功能是将二维数组中的a[0][0]、a[1][1]、a[2][2]和a[3][3]赋值给一维数组。最后将一维数组1,0,7,0,输出。 9.若有以下程序 #include #define N 4 void fun( int a[][N], int b[], int flag ) { inti,j; for( i=0; i { b[i] = a[0][i]; for( j=1; j if (flag ? (b[i] > a[j][i]) : (b[i] < a[j][i])) b[i] = a[j][i]; } } main() { int x[N][N]={1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16}, y[N],i; fun(x, y, 1); for (i=0;i fun(x, y, 0); for (i=0;i printf("\n"); } 则程序的输出结果是 A) 4,8,12,16,1,5,9,13, B) 1,2,3,4,13,14,15,16, C) 1,5,9,13,4,8,12,16, D) 13,14,15,16,1,2,3,4, 参考答案:B 【解析】该题首先初始化二维数组,if (flag ? (b[i] > a[i][j]) : (b[i] < a[i][j]))条件语句的条件表达式使用了条件运算符构成的选择结构,即flag为真时,以(b[i] > a[i][j])作为条件表达式的值,否则以(b[i] < a[i][j])作为条件表达式的值,fun函数功能是给一维数组赋值。fun(x, y, 1);该函数调用后,即当flag为真时,使一维数组获得二维数组第1行的数值;fun(x, y, 0);该函数调用后,即当flag为假时,使一维数组获得二维数组第4行的数值;因此B选项正确。 10.若有以下程序 #include #define N 4 void fun(int a[][N], int b[], int flag) { inti,j; for(i=0; i { b[i] = a[i][0]; for(j=1; j if (flag ? (b[i] > a[i][j]) : (b[i] < a[i][j])) b[i] = a[i][j]; } } main( ) { int x[N][N]={1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16}, y[N],i; fun(x, y, 1); for ( i=0; i fun(x, y, 0); for (i=0;i printf("\n"); } 则程序的输出结果是 A) 1,5,9,13,4,8,12,16, B) 4,8,12,16,1,5,9,13,C) 1,2,3,4,13,14,15,16, D) 13,14,15,16,1,2,3,4, 参考答案:A 【解析】该题首先初始化二维数组,if (flag ? (b[i] > a[i][j]) : (b[i] < a[i][j]))条件语句的条件表达式使用了条件运算符构成的选择结构,即flag为真时,以(b[i] > a[i][j])作为条件表达式的值,否则以(b[i] < a[i][j])作为条件表达式的值,fun函数功能是给一维数组赋值?fun(x, y, 1);该函数调用后,即当flag为真时,使一维数组获得二维数组第1列的数值;fun(x, y, 0);该函数调用后,即当flag为假时,使一维数组获得二维数组第4列的数值;因此A选项正确? 11.有以下程序 #include #define S(x) 4*(x)*x+1 main() { int k=5, j=2; printf("%d\n", S(k+j) ); } 程序运行后的输出结果是 A) 33 B) 197 C) 143 D) 28 参考答案:C 【解析】本题考查带参数的宏定义,S为带参数的宏定义,运行S(k+j)为4*(k+j)*k+j+1=143,选项C正确。12.有以下程序 #include #define SUB(a) (a)-(a) main() { int a=2,b=3,c=5,d; d=SUB(a+b)*c; printf("%d\n",d); } 程序运行后的输出结果是 A) 0 B) -12 C) -20 D) 10 参考答案:C 【解析】本题考查宏定义,宏定义只是做简单的替换,所以本题中SUB(a+b)*c=(a+b)-(a+b)*c=-20,所以答案为C选项。 13.有以下程序 #include #define f(x) x*x*x main() { int a=3,s,t ; s=f(a+1); t=f((a+1)); printf("%d,%d\n",s,t); } 程序运行后的输出结果是 A) 10,64 B) 10,10 C) 64,10 D) 64,64 参考答案:A 【解析】本题考查宏定义的用法,宏定义只是做个简单的替换,所以本题中执行 f(a+1)=a+1*a+1*a+1=3*a+1=10,f((a+1))=(a+1)*(a+1)*(a+1)=64,所以答案为A选项。 14.有以下程序 #include #define N 5 #define M N+1 #define f(x) (x*M) main() { int i1, i2; i1 = f(2) ; i2 = f(1+1) ; printf("%d %d\n", i1, i2); } 程序的运行结果是 A) 12 7 B) 12 12 C) 11 11 D) 11 7 参考答案:D 【解析】本题考查宏定义的用法,宏定义只是做个简单的替换,所以本题中执行f(2)=(2*N+1)=11,执行f(1+1)=(1+1*N+1)=7。选项D正确。 15.若有以下程序 #include #define S(x) x*x #define T(x) S(x)*S(x) main() { int k=5, j=2; printf("%d,%d\n", S(k+j),T(k+j)); } 则程序的输出结果是 A) 17,289 B) 49,2401 C) 17,37 D) 49,289 参考答案:C 【解析】本题考查宏定义,宏定义只是做个简单的替换,执行 S(k+j)=k+j*k+j=17,T(k+j)=S(k+j)*S(k+j)=k+j*k+j*k+j*k+j=37,选项C正确。 16.若有以下程序 #include #define S(x) (x)*(x) #define T(x) S(x)/S(x)+1 main() { int k=3, j=2; printf("%d,%d\n", S(k+j),T(k+j) ); } 则程序的输出结果是 A) 11,2 B) 25,2 C) 11,12 D) 25,26 参考答案:D 【解析】本题考查宏定义,宏定义只是做个简单的替换,执行 S(k+j)=(k+j)*(k+j)=25,T(k+j)=S(k+j)/S(k+j)+1=(k+j)*(k+j)/(k+j)*(k+j)+1=26,选项D正确。 17.有以下程序 #include #define N 2 #define M N+1 #define NUM (M+1) * M/2 main() { printf("%d\n",NUM ); } 程序运行后的输出结果是 A) 4 B) 8 C) 9 D) 6 参考答案:B 【解析】本题考查宏定义,宏定义只是做个简单的替换,执行NUM=(N+1+1)*N+1/2=8,选项B正确。 18.有以下程序 #include #define SUB( X, Y ) (X+1)*Y main() { int a=3, b=4; printf("%d\n",SUB(a++ ,b++ )); } 程序运行后的输出结果是 A) 25 B) 20 C) 12 D) 16 参考答案:D 【解析】本题考查宏定义,宏定义只是做个简单的替换,执行SUB(a++ ,b++)=(a++ +1)*b++=16,选项D正确。 19.有以下程序 #include #define SQR(X) X*X main() { int a=10, k=2, m=1; a /= SQR(k+m)/SQR(k+m); printf("%d\n",a); } 程序的输出结果是 A) 0 B) 1 C) 9 D) 10 参考答案:B 【解析】本题考查宏定义,宏定义只是做个简单的替换,执行SQR(k+m)/SQR(k+m)=k+m*k+m/ k+m*k+m=15/2, a/= SQR(k+m)/SQR(k+m)的结果为1,选项B正确。 20.以下叙述中正确的是 A) 在一个程序中,允许使用任意数量的#include命令行 B) 在包含文件中,不得再包含其他文件 C) #include命令行不能出现在程序文件的中间 D) 虽然包含文件被修改了,包含该文件的源程序也可以不重新进行编译和连接 参考答案:A 【解析】本题考查预处理中文件包含的概念,包含文件中可以包含其他文件,B选项错误,#include可以出现在程序文件的中间,C选项错误,包含文件被修改了,包含该文件的源程序必须重新进行编译和连接。 21.以下四个程序中,完全正确的是()。 A) #include main();main() {/*/ programming /*/ {/* programming */ printf("programming!\n");} printf("programming!\n");} C) #include main() main() {/*/* programming */*/ {/* programming */ printf("programming!\n");} printf("programming!\n");} 参考答案:B 【解析】C语言中注释语句的注释方法是:/* 注释内容*/ 或//注释一行。所以A)与C)错误,D)选项中预编译命令include 22.以下叙述中错误的是 A) C程序对预处理命令行的处理是在程序执行的过程中进行的 B) 预处理命令行的最后不能以分号表示结束 C) #define MAX 是合法的宏定义命令行 D) 在程序中凡是以"#"开始的语句行都是预处理命令行 参考答案:A 【解析】本题考查预处理命令行,预处理是在程序编译之前进行的,所以A选项错误。 23.下面选项中关于编译预处理的叙述正确的是 A) 预处理命令行必须使用分号结尾 B) 凡是以#号开头的行,都被称为编译预处理命令行 C) 预处理命令行不能出现在程序的最后一行 D) 预处理命令行的作用域是到最近的函数结束处 参考答案:B 【解析】本题考查预编译的预编译处理命令行,预处理命令行不能以分号结尾,所以A选项错误,预处理命令行可以出现在程序的最后一行,预处理命令行作用域是整个文件 24.有以下程序段 int *p; p= __________ malloc( sizeof( int )); 若要求使p指向一个int型的动态存储单元,在横线处应填入的是 A) (int *) B) int C) int * D) ( *int ) 参考答案:A 【解析】本题考查malloc函数,题目中要求p指向一个int型的动态存储单元,那么就应该将分配的存储单元转化为int,所以选项A正确。 第九章编译预处理 9.1 选择题 【题9.1】以下叙述中不正确的是。 A)预处理命令行都必须以#号开始 B)在程序中凡是以#号开始的语句行都是预处理命令行 C)C程序在执行过程中对预处理命令行进行处理 D)以下是正确的宏定义 #define IBM_PC 【题9.2】以下叙述中正确的是。 A)在程序的一行上可以出现多个有效的预处理命令行 B)使用带参的宏时,参数的类型应与宏定义时的一致 C)宏替换不占用运行时间,只占编译时间 D)在以下定义中C R是称为“宏名”的标识符 #define C R 045 【题9.3】请读程序: #define ADD(x) x+x main() { int m=1,n=2,k=3; int sum=ADD(m+n)*k; printf(“sum=%d”,sum); } 上面程序的运行结果是。 A)sum=9 B)sum=10 C)sum=12 D)sum=18 【题9.4】以下程序的运行结果是。 #define MIN(x,y) (x)<(y)?(x):(y) main() { int i=10,j=15,k; k=10*MIN(i,j); printf(“%d\n”,k); } A)10 B)15 C)100 D)150 【题9.5】在宏定义#define PI 3.14159中,用宏名PI代替一个。 A)常量B)单精度数C)双精度数D)字符串 【题9.6】以下程序的运行结果是。 #include 第九章编译预处理 一、单选题 1.以下对宏替换的叙述不正确的是 A)宏替换只是字符的替换B)宏替换不占运行时间 C)宏名无类型,其参数也无类型 D)带参的宏替换在替换时,先求出实参表达式的值,然后代入形参运算求值2.宏定义#define PI 3.14中的宏名PI代替 A)一个单精度实数)B)一个双精度实数 C)一个字符串 D)不确定类型的数 3.有以下宏定义 #define k 2 #define X(k) ((k+1)*k) 当C程序中的语句y = 2 * (K + X(5));被执行后, A)y中的值不确定 B)y中的值为65 C)语句报错 D)y中的值为34 4.以下程序的输出结果是 #define MIN(x, y) (x) < (y) ? (x) : (y) main() { int i , j, k; i = 10; j = 15; k = 10 * MIN(i, j); printf(“%d\n”, k); } A)15 B)100 C)10 D)150 5.以下程序中的for循环执行的次数是 #define N 2 #define M N + 1 #define NUM (M + 1) * M / 2 main() { int i; for(i = 1; i <= NUM; i++); pritnf(“%d\n”, i ); } A)5 B)6 C)8 D)9 6.以下程序的输出结果是 #include “stdio.h” #define FUDGF(y) 2.84 + y #define PR(a) printf(“%d”, (int) ( a ) ) #define PRINT1(a) PR(a); putchar(‘\n’) main() { int x = 2; PRINTF1(FUDGF(5) * X); } A)11 B)12 C)13 D)15 7.以下程序的输出结果是 #define FMT “%d,” main() 第九章编译预处理 课题:第九章编译预处理 教学目的:1、了解预处理的概念及特点 2、掌握有参宏与无参宏的定义及使用,领会文件包含的使用及效果 教学重点:教学难点:掌握宏的使用,文件包含有参宏与无参宏的使用 步骤一复习引导 ANSI C标准规定可以在C源程序中加入一些“预处理命令”,以改进程序设计环境,提高编程效率。 这些预处理命令是由ANSI C统一规定的,但它不是C语言本身的组成部分,不能直接对它们进行编译。必须在对程序进行通常的编译之前,先对程序中这些特殊的命令进行“预处理”,即根据预处理命令对程序作相应的处理。经过预处理后程序不再包括预处理命令了,最后再由编译程序对预处理后的源程序进行通常的编译处理,得到可供执行的目标代码。 步骤二讲授新课 C语言与其他高级语言的一个重要区别是可以使用预处理命令和具有预处理的功能。C 提供的预处理功能主要有以下三种:宏定义、文件包含、条件编译。 分别用宏定义命令、文件包含命令、条件编译命令来实现。为了与一般C语句相区别,这些命令以符号“ #” 开头。 §9.1宏定义 宏:代表一个字符串的标识符。 宏名:被定义为“宏”的标识符。 宏代换(展开):在编译预处理时,对程序中所有出现的“宏名”,用宏定义中的字符串去代换的过程。 一、不带参数的宏定义 一般形式:#define 标识符字符串 #define PI 3.1415926 main() { float l, s, r, v; printf( “input radius:” ); scanf( “%f”, &r ); l = 2.0*PI*r; s = PI*r*r; v = 3.0/4*PI*r*r*r; printf(“%10.4f,%10.4f,%10.4\n”, l, s, v); } 第9章预处理命令 宏定义不是C语句,所以不能在行尾加分号。如果加了分号则会连分号一起进行臵换。 可以用#undef命令终止宏定义的作用域。 对程序中用“”括起来的内容(即字符串内的字符),即使与宏名相同,也不进行臵换。宏定义只做字符替换,不分配内存空间。 宏名不是变量,不分配存储空间,也不能对其进行赋值。 在宏展开时,预处理程序仅对宏名作简单的字符串替换,不作任何检查。 在进行宏定义时,可以引用已定义的宏名 无参宏定义的一般格式: #define 标识符字符串 将这个标识符(名字)称为“宏名”,在用预编译时将宏名替换成字符串的过程称为“宏展开”。#define是宏定义命令。 带参宏定义的一般格式: #define 宏名(形参表)字符串 带参宏的调用和宏展开: 调用格式:宏名(实参表); 宏展开(又称为宏替换)的方法:用宏调用提供的实参直接臵换宏定义中相应的形参,非形参字符保持不变。 定义有参宏时,宏名与左圆括号之间不能留有空格。否则,C编译系统会将空格以后的所有字符均作为替代字符串,而将该宏视为无参宏。 有参宏的展开,只是将实参作为字符串,简单地臵换形参字符串,而不做任何语法检查。 为了避免出错,可以在所有形参外,甚至整个字符串外,均加上一对圆括号。 如: #define S(r) 3.14*(r)*(r) 则:area=S(a+b); 展开后为: area=3.14*(a+b)*(a+b); 调用有参函数时,是先求出实参的值,然后再复制一份给形参。而展开有参宏时,只是将实参简单地臵换形参。函数调用是在程序运行时处理的,为形参分配临时的内存单元;而宏展开则是在编译前进行的,在展开时不分配内存单元,不进行值的传递,也没有“返回值”的概念。调用函数只可得到一个返回值,而用宏可以设法得到几个结果。 在有参函数中,形参都是有类型的,所以要求实参的类型与其一致;而在有参宏中,形参和宏名都没有类型,只是一个简单的符号代表,因此,宏定义时,字符串可以是任何类型的数据。 使用宏次数多时,宏展开后源程序变长,因为每展开一次都是程序增长,而函数调用不会使源程序变长。 宏替换不占用运行时间,只占编译时间。而函数调用则占用运行时间(分配单元、保留现场、值传递、返回)。 在程序中如果有带实参的宏,则按#define命令行中指定的字符串从左到右进行臵换。如果字符串中包含宏中的形参,则将程序语句中相应的实参(可以是常量、变量或表达式)代替形参。如果宏定义中的字符串中的字符不是参数字符,则保留。 1.以下叙述中正确的是()。 A) 在C语言中,预处理命令行都以"#"开头 B) 预处理命令行必须位于C源程序的起始位置 C) #include 第九章编译预处理与带参数的主函数 一、单项选择题 1.C程序中,以#号带头的行是预编译(A)。 A.命令 B.语句 C.函数 D.字符串 2.下列正确的预编译命令是(B)。 A.define PI 3.14159 B.#define p(a,b) strcpy(a,b) C. #include stdio.h D. # define PI3.14159 3.下列命令或语句中,正确的是(C)。 A.#define MYNAME= “ABC” B.#include stdio.h C. for(i=0;i<10;i++); D.struct int stu{int name}; 4.下列命令或语句中,正确的是(A)。 A.#define PI 3.14159 B. include “stdio.h” C.for(i=0,i<10,i++)a++ D.static struct {int i;}b={2}; 5.下列命令或语句中,错误的是(B)。 A. #define PI 3.14159 B.#include 第九章预处理 A部分(本、专科必做) 一、选择题 以下不正确的叙述是(D) A、宏替换不占用运行时间。 B、宏名无类型。 C、宏替换只是字符替换。 D、宏名必须用大写字母表示。 C语言的编译系统对宏命令的处理(D) A、在程序运行时进行的。 B、在程序连接时进行。 C、和C程序中的其它语句同时进行编译的。 D、在对源程序中其它语句正式编译之前进行的。 3、以下程序的输出结果是(C)。 A、15 B、100 C、10 D、150 #define MIN(x,y) (x)<(y)?(x):(y) void main() { int I,j,k; i=10;j=15;k=10*MIN(i,j); printf(“%d\n”,k); } 4、以下叙述中正确的是(D) 用#include包含的文件的后缀必须是“.h”。 若一些源程序中包含某个头文件;当该文件有错时,只需对该头文件进行修改,包含此头文件的所有源程序不必重新进行编译。 宏命令行可以看作是一行C语句。 预处理是在编译之前进行的。 5、以下叙述中正确的是(C) A、源程序中所有的行都参加编译。 B、宏定义常量与const定义常量是一样的。 C、宏定义可以嵌套定义,即在宏定义中的字符串可以引用另一个宏定义的标识符。 D、以上都不正确。 二、填空题 以下程序中for 循环执行的次数是 6 。 #define N 2 #define M N+1 #define NUM (M+1)*M/2 void main() { int i; for(i=1;i<=NUM;i++); printf(“%d\n”,i); } 2、以下程序的输出结果是x=93 。 #define A 3 #define B(a) ((A+1)*a) 第九章习题答案 一、单项选择题 1.A 2.B 3.C 4.D 5.B 6.C 7.A 8.D 9.D 10.C 11.B 12.C 13.D 14.C 二、填充题 1.编译处理编译预处理 2.非静态存储类型变量和外部函数 3.7 4.printf(“%d\n”,m); 5.fopen(“a.txt”,”rw”); 6.x[i]>=’A’&&x[i]<=’Z’ 7.“ i=%d\n” 8.(1) #define MAX(a,b,c) (2) #define MIN(a,b) (a=’0’&& c<=’9’) (4) #define isupper( c) (c>=’A’&& c<=’Z’) (5) #define islower( c) (c>=’a’ && c<=’z’) 三、程序分析题 1.运行结果: -3 2.运行结果: 7,47 3.运行结果:50 25 4.运行结果:x=9, y=5 5.运行结果:9 9 11 6.输出结果: x|y&z=3 x^y&~z=1 x&y&z=0 !x|x=1 ~x|x=-1 四、程序设计题 1.解: #include 第九章 编译预处理 编译指令(编译预处理指令):C 源程序除了包含程序命令(语句)外,还可以使用各种编译指令(编译预处理指令)。编译指令(编译预处理指令)是给编译器的工作指令。这些编译指令通知编译器在编译工作开始之前对源程序进行某些处理。编译指令都是用“#”引导。 编译预处理:编译前根据编译预处理指令对源程序的一些处理工作。C 语言编译预处理主要包括宏定义、文件包含、条件编译。 编译工作实际分为两个阶段:编译预处理、编译。广义的编译工作还包括连接。 9、1 宏定义 宏定义:用标识符来代表一个字符串(给字符串取个名字)。C 语言用“#define ”进行宏定义。C 编译系统在编译前将这些标识符替换成所定义的字符串。 宏定义分为不带参数的宏定义和带参数宏定义。 9、1、1 不带参数宏定义(简单替换) 1 其中:标识符-宏名。 2、宏调用:在程序中用宏名替代字符串。 3、宏展开:编译预处理时将字符串替换宏名的过程,称为宏展开。 说明: (1)宏名遵循标识符规定,习惯用大写字母表示,以便区别普通的变量。 (2)#define 之间不留空格,宏名两侧空格(至少一个)分隔。 (3)宏定义字符串不要以分号结束,否则分号也作为字符串的一部分参加展开。从这点上 看宏展开实际上是简单的替换。 例如:#define PI 3.14; 展开为s=3.14;*r*r ;(导致编译错误) (4)宏定义用宏名代替一个字符串,并不管它的数据类型是什么,也不管宏展开后的词法 和语法的正确性,只是简单的替换。是否正确,编译时由编译器判断。 例如:#define PI 3.I4 照样进行宏展开(替换),是否正确,由编译器来判断。 (5)#define 宏定义宏名的作用范围从定义命令开始直到本源程序文件结束。可以通过 #undef 终止宏名的作用域。 第九章 预处理命令 一、选择题 1.以下叙述不正确的是 。 A)预处理命令行都必须以#开始 B)在程序中凡是以#开始的语句行都是预处理命令行 C)C程序在执行过程中对预处理命令行进行处理 D)预处理命令行可以出现在C程序中任意一行上 2.以下叙述中正确的是 。 A)在程序的一行上可以出现多个有效的预处理命令行 B)使用带参数的宏时,参数的类型应与宏定义时的一致 C)宏替换不占用运行时间,只占用编译时间 D)C语言的编译预处理就是对源程序进行初步的语法检查 3.以下有关宏替换的叙述不正确的是 。 A)宏替换不占用运行时间B)宏名无类型 C)宏替换只是字符替换D)宏名必须用大写字母表示 4.在“文件包含”预处理命令形式中,当#include后面的文件名用””(双引号)括起时,寻找被包含文件的方式是 。 A)直接按系统设定的标准方式搜索目录 B)先在源程序所在目录中搜索,再按系统设定的标准方式搜索 C)仅仅搜索源程序所在目录 D)仅仅搜索当前目录 5.在“文件包含”预处理命令形式中,当#include后名的文件名用<>(尖括号)括起时,寻找被包含文件的方式是 。 A)直接按系统设定的标准方式搜索目录 B)先在源程序所在目录中搜索,再按系统设定的标准方式搜索 C)仅仅搜索源程序所在目录 D)仅仅搜索当前目录 6.在宏定义#define PI 3.1415926中,用宏名PI代替一个 。 A)单精度数B)双精度数C)常量D)字符串 7.以下程序的运行结果是 。 #include (1) 下面叙述错误的是()。 A) “#define PRICE 30”命令的作用是定义一个与30等价的符号常量PRICE B) C源程序中加入一些预处理命令是为了改进程序设计环境,提高编程效率 C) “#include A、第一维和第二维都为4 B、第一维和第二维都为3 C、第一维为4,第二维为3 D、第一维为3,第二维为4 (7) 下列程序的运行结果是()。 # define M 5 # define N M+1 # define NN N*N-M void main( ) { printf(“%d\n”,3*NN); } A、108 B、16 C、21 D、103 (8) 下列叙述正确的是()。 A、宏定义中的宏名必须用大写字母表示 B、为提高程序运行速度可在源程序中加入一些宏定义 C、一个C语言源程序只能有一条预处理命令 D、宏定义不占用程序运行时间,但与程序中的语句一样需要编译 (9) 下列叙述错误的是()。 A、宏定义可出现在源程序中任意合适的位置,且必须在行末加分号 B、预处理命令行都必须以#号开始 C、C语言源程序中加入一些预处理命令是为了改进程序设计环境,提高编程效率 D、# define PER 1.5的作用是用标识符PER代表1.5 (10) 下列程序的运行结果是()。 # define K 5 void main( ) { int a=3,b=4; printf(“%d\n”,K*(a+b)); } A、20 B、15 C、5 D、35 (11) 以下叙述正确的是()。 A) 一个源程序只能由一个编译预处理命令行 B) 编译预处理命令都必须以"#"开头 C) "#define PRICE=30"定义了与30等价的符号常量PRICE 第九章编译预处理 预处理功能主要有三种:宏定义;文件包含;条件编译。 9.1宏替换(宏定义) 9.1.1不带参数的宏定义 1. #define 指令:用一个指定的标识符来代表一个字符串。 2.定义的一般形式是: #define 宏名字符串(或数值) 由#define指令定义后, 在程序中每次遇到该宏名时就用所定义的字符串(或数值)代替它。 例1:#define PI 3.14159265 #define RADIUS 2.0 double circum() { return(2.0*PI*RADIUS); } double area() { return(PI*RADIUS*RADIUS); } main() { printf("L=%lf\n",circum()); printf("S=%lf\n",area()); } 注意: ①在宏定义的后面没有";"(因为它不是语句) ②习惯上用大写字符作为宏名, 与变量名相区别,而且常放在程序开头。 ③使用宏名代替一个字符串,可以减少程序中重复书写某些字符串的工作量: #define array_size 1000 int array[attay_size]; ④可以用#undef命令终止宏定义的作用域。 #define G 9.8 main() { } #undef G f1( ) …….. ⑤在进行宏定义时,可以引用已定义的宠名,可以层层置换。 例:#define R 3.0 #define PI 3.1415926 #define L 2*PI*R #define S PI*R*R main() { printf(“L=%f\ns=%f\n”,L,S); } ⑥在程序中用双引号括起来的字符串骨近字符,与宏名相同,不进行置换,作为字符串。 9.1.2带参数的宏定义 1.# define 宏名(参数)字符串 不是进行简单的字符串替换,还要进行参数替换。 例2: #define MAX(x, y) ((x)>(y))?(x):(y) main() { int i=10, j=15; printf("The Maxmum is %d", MAX(i, j)); } 展开相当于: printf("The Maxmum is %d", ((i)>(j))?(i):(j)); 9.2.“文件包含”处里(#include) 1.定义:#include 指令的作用是指示编译器将该指令所指出的另一个源文件嵌入#include指令所在的程序中.其一般形式为:#include <文件名> 或#include “文件名” 第一种形式:系统到系统标准目录中搜索该文件 第二种形式:首先到当前目录中搜索该文件,如找不到则到系统标准目录中去搜索该文件。 例3: 输入一个句子,统计单词个数。 首先编写一个头文件: /*hong.h*/ #include 编译预处理
第九章 编译预处理
C语言程序设计教案 第九章 编译预处理
第9章 预处理命令
C二级 第9章 编译预处理和动态存储分配
第九章编译预处理与带参数的主函数
第九章 预处理
第九章改 预处理命令习题答案
第九章编译预处理
第九章 预处理命令
第九章预处理的考试试题
第八章 编译预处理