八、 编译预处理
本章概述:
以笔试和上机两种形式考核。笔试中,多出现在选择题第28-30题,分值约占2%。上机中,会考查“宏定义和调用”,抽中几率约为2%。
编译预处理:编译前预先要做的工作。预处理是C语言的一个重要功能,对一个源程序进行编译前,系统自动引用预处理程序对源程序中的预处理部分作处理。处理完毕再进入对源程序的编译。C语言提供了多种预处理功能,如宏定义、文件包含、 条件编译等。
大纲要求:
1.宏定义和调用(不带参数的宏,带参数的宏)。
2.“文件包含”处理。
重点难点:
1. 宏定义
考点分析:
不带参数的宏定义
宏定义的一般形式:
#define 标识符 字符串
标识符称为这串字符的宏名,在程序中用宏名替代字符串称为宏调用。预编译时将字符串替换宏名的过程称为宏展开。
说明
关于失联党员情况说明岗位说明总经理岗位说明书会计岗位说明书行政主管岗位说明书
:
⑴ 宏名一般用大写字母
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
示,以便与普通变量相区别。
⑵ #与define间一般不留空格,宏名两侧必须至少用一个(可以多个)空格分隔。
⑶ 宏定义字符串后不能以分号结尾,否则分号将作为字符串的一部分参加宏展开,造成编译时出错。
⑷ 宏定义用宏名代替一个字符串,并不管它的数据类型是什么,也不管词法和语法是否正确,只作简单的替换。
⑸ #define命令定义的宏名作用范围是从定义命令开始直到源程序文件结束,一般情况下,#define总是定义在文件开头,函数之间。还可以在程序中通过#undef终止宏名的作用域。
⑹ 宏定义中,可以出现已定义的宏名,还可以层层置换。
⑺ 若宏名出现在一个被双引号括起来的字符串中时,将不会产生宏替换。
宏定义与定义变量不同:
宏定义是专用于预处理的一个名词,它与定义变量含义不同,只用字符简单替换,不分配内存空间。
· 试题解析
1.程序如下:
#define R 3.0
#define PI 3.1415926
#define L 2*PI*R
#define S PI*R*R
main()
{
printf("L=%7.2f\nS=%7.2f\n",L,S);
}
运行结果:
L=18.85
S=28.27
解析:经过宏展开后,printf函数中的输出项L被展开成2*3.1415926*3.0,S展开成3.1415926*3.0*3.0,双引号内的L,S不作替换。
带参数的宏定义
带参数的宏定义一般形式:
C语言允许宏带有参数。在宏定义中的参数称为形式参数,在宏调用中的参数称为实际参数。对带参数的宏,在调用中不仅要宏展开,而且要用实参去代换形参。带参数的宏定义一般形式为:
#define 宏名(参数表) 字符串
例如,#define S(a,b) a*b
area=S(3,2);
这里S为宏名,a和b为形式参数;程序中调用S(3,2)时,把实参3与2分别代替形参a与b,因此,赋值语句宏展开为
area=3*2;
对带参的宏定义展开
规则
编码规则下载淘宝规则下载天猫规则下载麻将竞赛规则pdf麻将竞赛规则pdf
如下:在程序中如果有带实参的宏(如S(3,2)),则按#define命令行中指定的字符串从左到右进行置转,如果串中包含宏中的形参(如a,b),则将程序语句中相应的实参(可以是常量、变量或表达式)代替形参,其它字符则原样保留,这样就形成了替换后的字符串。
说明:
(1) 带参数宏定义中,宏名和形参表之间不能有空格出现。
(2) 在宏定义中的形参是标识符,而宏调用中的实参可以是表达式。
带参数的宏与函数的区别:
⑴ 函数调用时,先求出实参表达式的值,再将该值传递给形式参数。而带参的宏只进行简单的字符置换。不求实参值。
⑵ 函数调用是在程序运行时处理的,分配给形参临时内存单元。而宏展开则在编译时进行的,展开时并不给形参分配内存单元,不进行“值传递”,也没有“返回值”。
⑶ 在函数中使用的实参与形参都要定义类型,而且两者类型要求一致,如不一致,需进行类型转换。宏不存在参数的类型问题,它只是一个符号而已,展开后的表达式类型随实参类型不同,呈现出不同的数据类型。
· 试题解析
1.用带参数的宏定义求两数中的大数并输出。
#define MAX(a,b) (a>b)?a:b
main()
{int i,j;
i=15;
j=20;
printf("MAX=%d\n",MAX(i,j));
}
运行结果
MAX=20
解析:该程序在编译前,表达式MAX(i,j)被定义的字符串所替换,其中的i和j作为实参替换字符串中对应的形参a和b,其它符号不变。printf语句经宏展开成
printf("MAX=%d\n",(i>j)?i:j);
2.设有如下宏定义
#define MYSWAP(z,x,y) {z=x;x=y;y=z;}
以下程序段通过宏调用实现变量a、b内容的交换,请填空。
float a=5,b=16,c;
MYSWAP(【15】,a,b);
解析:本题关键在考生是不是了解宏的基本运用,在使用宏的时候明显少了一个实参。在定义宏的时候变量z是用来做中间变量的,题目中缺的变量就是一个中间变量c。
3.带参数的宏替换与函数的比较:
三角形的面积为
area=
其中s=,a、b、c为三角形的三边。
解析:
⑴ 使用带参数的宏替换
define S(a,b,c) (a+b+c)/2
#define AREA(a,b,c) sqrt(S(a,b,c)*(S(a,b,c)-a)*(S(a,b,c)-b)*(S(a,b,c)-c))
#include "math.h"
main()
{float a,b,c;
scanf("%f%f%f",&a,&b,&c);
printf("AREA=%7.2f",AREA(a,b,c));
}
运行结果
3 4 5 ↙
AREA=6.00
⑵ 使用函数
#include "math.h"
float area(float x,float y,float z)
{float s,t;
s=(x+y+z)/2;
t=sqrt(s*(s-x)*(s-y)*(s-z));
return t;
}
main()
{float a,b,c;
scanf("%f%f%f",&a,&b,&c);
printf("AREA=%7.2f",area(a,b,c));
}
运行结果
3 4 5 ↙
AREA=6.00
文件包含
文件包含:
文件包含命令的功能是把指定的文件插入该命令行位置取代该命令行,从而把指定的文件和当前的源程序文件连成一个源文件。
文件包含的一般形式为:
#include “文件名” 或 #include <文件名>
说明:
(1) 包含命令中的文件名可以用双引号括起来,也可以用尖括号括起来。这两种形式的区别是:使用尖括号表示在包含文件目录中去查找(包含目录是由用户在设置环境时设置的), 而不在源文件目录去查找; 使用双引号则表示首先在当前的源文件目录中查找,若未找到才到包含目录中去查找。用户编程时可根据自己文件所在的目录来选择某一种命令形式。
(2) 一个include命令只能指定一个被包含文件,若有多个文件要包含,则需用多个include命令;
(3) 文件包含允许嵌套,即在一个被包含的文件中又可以包含另一个文件;
· 试题解析
1.以下叙述中正确的是(B)
A 预处理命令行必须位于C源程序的起始位置
B 在C语言中,预处理命令行都以"#"开头
C 每个C程序必须在开头包含预处理命令行:#include
D C语言的预处理不能实现宏定义和条件编译的功能
解析:预处理命令可以放在程序中的任何位置,其有效范围是从定义开始到文件结束。预处理命令有宏定义、文件包含和条件编译三类。只是其中的一个文件,并不说每次预处理命令都用此文件。
相关习题
一、选择题
(1)有以下程序
main()
{ char p[]={'a', 'b', 'c'}, q[]="abc";
printf("%d %d\n", sizeof(p),sizeof(q));
};
程序运行后的输出结果是
A)4 4 B)3 3 C)3 4 D)4 3
(2)有以下程序
# define f(x) (x*x)
main()
{ int i1, i2;
i1=f(8)/f(4) ; i2=f(4+4)/f(2+2) ;
printf("%d, %d\n",i1,i2);
}
程序运行后的输出结果是
A)64, 28 B)4, 4 C)4, 3 D)64, 64
(3)有以下程序
main()
{ char a[7]="a0\0a0\0";int i,j;
i=sizeof(a); j=strlen(a);
printf("%d %d\n",i,j);
}
程序运行后的输出结果是
A)2 2
B)7 6
C)7 2
D)6 2
(4)以下叙述中正确的是
A)预处理命令行必须位于源文件的开头
B)在源文件的一行上可以有多条预处理命令
C)宏名必须用大写字母表示
D)宏替换不占用程序的运行时间
(5) 有以下程序
main( )
{ char a[]=”abcdefg”,b[10]=”abcdefg”;
printf(“%d %d\n”,sizeof(A) ,sizeof(B) );
}
执行后输出结果是
A) 7 7 B) 8 8 C) 8 10 D) 10 10
(6) 有以下程序
#define f(x) x*x
main( )
{ int i;
i=f(4+4)/f(2+2);
printf(“%d\n”,i);
}
执行后输出结果是
A) 28 B) 22 C) 16 D) 4
(7) 有以下程序
#include
#define F(X,Y) (X)*(Y)
main ()
{ int a=3, b=4;
printf("%d\n", F(a++,b++));
}
程序运行后的输出结果是
A) 12 B) 15 C) 16 D) 20
(8) 有以下程序
main()
{ char s[]="\n123\\";
printf("%d,%d\n",strlen(s),sizeof(s));
}
执行后输出结果是
A) 赋初值的字符串有错 B) 6,7 C) 5,6 D) 6,6
(9) 有以下程序
main(int arge,char *argv[])
{ int n,i=0;
while(arv[1][i]!='\0'
{ n=fun(); i++;}
printf(%d\n",n*argc);
}
int fun()
{ static int s=0;
s+=1;
return s;
}
假设程序经编译、连接后生成可执行文件exam.exe,若键入以下命令行
exam 123<回车>
则运行结果为
(10) 有以下程序
main()
{ char a[ ]={‘a’,‘b’,‘c’,‘d’, ‘e’, ‘f’, ‘g’,‘h’,‘\0’}; int i,j;
i=sizeof(a); j=strlen(a);
printf(“%d,%d\b”i,j);
}
程序运行后的输出结果是
A)9,9 B)8,9 C)1,8 D)9,8
(11) 程序中头文件typel.h 的内容是:
#define N 5
#define M1 N*3
程序如下:
#define “type1.h”
#define M2 N*2
main()
{ int i;
i=M1+M2; printf(“%d\n”,i);
}
程序编译后运行的输出结果是:
A) 10 B) 20 C) 25 D) 30
(12) 有以下程序
#include
main()
{ char *p,*q;
p=(char*)malloc(sizeof(char)*20); q=p;
scanf(“%s%s”,p,q); printf(“%s%s\n”,p,q);
}
若从键盘输入:abc def<回车>,则输出结果是:
A) def def B) abc def C) abc d D) d d
(13) 若指针p已正确定义,要使p指向两个连续的整型动态存储单元,不正确的语句是
A) p=2*(int*)malloc(sizeof(int));
B) p=(int*)malloc(2*sizeof(int));
C) p=(int*)malloc(2*2);
D) p=(int*)calloc(2,sizeof(int));
(14) 以下程序的输出结果是
main()
{ char st[20]= “hello\0\t\\\”;
printf(%d %d \n”,strlen(st),sizeof(st));
}
A) 9 9 B) 5 20 C) 13 20 D) 20 20
(15) 以下程序的输出结果是
amovep(int p, int (a)[3],int n)
{ int i, j;
for( i=0;i<;i++)
for(j=0;j
#define PT 5.5
#define S(x) PT* x * x
main()
{ int a=1,b=2;
printf("%4.1f\n",S(a+b));
}
(25) 以下程序运行后,输出结果是
A) 1 B) 7 C) 9 D) 11
fut(int **s, int p[2][3])
{ **s=p[1][1];}
main()
{ int a[2][3]={1,3,5,7,9,11}, *p;
p=(int *) malloc(sizeof(int));
fut(&p,a);
printf("%d\n",*P);
}
(26) 设有以下宏定义:
#define N 3
#define Y(n) ( (N+1)*n)
则执行语句:z=2 * (N+Y(5+1));后,z的值为
A) 出错 B) 42 C) 48 D) 54
(27) 若有说明,double *p,a;则能通过scanf语句正确给输入项读入数据的程序段是
A)*p=&a; scanf("%lf",p); B)p=(double *)malloc(8);scanf("%f",p);
C) p=&a;scanf("%lf",a); D)p=&a; scanf("%le",p);
(28) 执行下面的程序后,a的值是
#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) 10 B) 1 C) 9 D) 0
(29) 以下程序的输出结果是
fut (int**s,int p[2][3])
{ **s=p[1][1]; }
main( )
{ int a[2][3]={1,3,5,7,9,11},*p;
p=(int*)malloc(sizeof(int));
fut(&p,a);
primtf("%d\n",*p); }
A) 1 B) 7 C) 9 D) 11
(30) 若要用下面的程序片段使指针变量p指向一个存储整型变量的动态存储单元:
int *p;
p=__________ malloc( sizeof(int));
则应填入
A) int B) inst * C) (*int) D) (int *)
(31) 请读程序:
#include
#define SUB(X,Y) (X)*Y
main()
{ int a=3, b=4;
printf("%d", SUB(a++, b++));
}
上面程序的输出结果是
A) 12 B) 15 C) 16 D) 20
(32) 请读程序:
#include
void fun(float *pl, float *p2, float *s)
{ s=( float * )calloc( 1, sizeof(float));
*s=*p1+ *(p2++);
}
main()
{ float a[2]={1.1, 2.2}, b[2]={10.0, 20.0}, *s=a;
fun(a, b, s)
printf("%f\n",*s);
}
上面程序的输出结果是
A) 11.100000 B) 12.100000 C) 21.100000 D) 1.100000
(33) 在宏定义 #define PI 3.14159中,用宏名PI代替一个
A) 单精度数 B) 双精度数 C) 常量 D) 字符串
(34) 请选出以下程序段的输出结果
#include
#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
(35) sizeof(double)是 【35】 。
A)一种函数调用 B)一个双精度型表达式
C)一个整型表达式 D)一个不合法的表达式
(36) 以下for语句构成的循环执行了 【36】 次。
# include
# define N 2
# define M N+1
# define NUM (M+1)*M/2
main()
{ int i , n=0;
for ( i=1;i<=NUM;i + + );
{n + + ; printf("%d",n); }
printf("\n"); }
A) 5 B) 6 C) 8 D) 9
(37) 以下程序的输出结果是 【37】 。
# include
# define FUDGE(y) 2.84+y
# define PR(a) printf("%d",(int)(a))
# define PRINT1(a) PR(a);putchar('\n')
main()
{int x=2; PRINT1(FUDGE(5)*x); }
A) 11 B) 12 C) 13 D) 15
二、填空题:
(1)已有定义:double *p;,请写出完整的语句,利用malloc函数使p指向一个双精度型的动态存储单元 【1】 。
(2)以下程序运行后的输出结果是 【2】 .
#define S(x) 4*x*x+1
main()
{
int i=6,j=8;
printf("%d\n",S(i+j));
}
(3) 以下程序中, for循环体执行的次数是 【3】 。
#define N 2
#define M N+1
#define K M+1*M/2
main()
{ int i;
for(i=1;i
main ( )
{ double *p;
p=(double *) malloc(【4】);
p[0]=1.5;p[1]=2.5;p[2]=3.5;
printf(“%f%f%f\n”,p[0],p[1],p[2]);
}
(5) 以下程序的输出结果是【5】 。
#defint MCRA(m) 2*m
#define MCRB(n,m) 2*MCRA(n)+m
main()
{ int i=2,j=3;
printf("%d\n",MCRB(j,MCRA(i)));
}
(6) 下面程序的运行结果是【6】 。
#define N 10
#define s(x) x*x
#define f(x) (x*x)
main()
{ int i1,i2;
i1=1000/s(N); i2=1000/f(N);
printf(“%d %d\n”,i1,i2);
}
(7) 设有如下宏定义
#define MYSWAP(z,x,y) {z=x; x=y; y=z;}
以下程序段通过宏调用实现变量a、b内容交换,请填空。
float a=5,b=16,c;
MYSWAP( 【7】 ,a,b);
(8) 用以下语句调用库函数malloc,使字符指针st指向具有11个字节的动态存储空间,请填空。
st=(char*) 【8】 ;
(9) 以下程序的输出结果是【9】。
#define MAX(x,y) (x)>(y)?(x):(y)
main()
{ int a=5,b=2,c=3,d=3,t;
t=MAX(a+b,c+d)*10;
printf(“%d\n”,t);
}
(10) 若要使指针p指向一个double类型的动态存储单元,请填空。
p= 【10】 malloc(sizeof(double));
(11) 下面程序的输出是 【11】 。
#define PR(ar) printf("%d", ar)
main()
{ int j, a[]={ 1,3,5,7,9,11,13,15}, *p=a+5;
for(j=3; j; j--)
{ switch(j)
{ case 1:
case 2: PR(*p++); break;
case 3: PR(*(--p));}
}
}
答案
八年级地理上册填图题岩土工程勘察试题省略号的作用及举例应急救援安全知识车间5s试题及答案
:
一、选择题:
1) C 2) C 3) C 4) D 5) C 6) A 7) A 8) C 9) A 10) D
11) C 12) A 13) A 14) B 15) A 16) D 17) B 18) C 19) B 20) B
21) A 22) D 23) C 24) B 25) C 26) C 27) D 28) B 29) C 30) D
31) A 32) D 33) D 34) A 35) C 36) C 37) B
二、填空题:
(1) p=(double*)malloc(sizeof(double))
(2) 81 (3) 4
(4) 3*sizeof(double) (5) 16 (6) 1000 10
(7) c (8) Malloc (11) 或malloc(sizeof(char)*11)
(9) 7 (10) (double *) (11) 9911
考点1
考点2
考点3
_1107705998.unknown
_1107706069.unknown