预处理问题
1.什么是预处理,编辑源程序->预处理后的源程序-> 目标程序链接-> 可执行程序
ANSI C标准规定可以在C源程序中加入一些“预处理命令”,以改进程序设计环境,提高编程效 率。在对程序进行通常的编译之前,先对程序中特殊的命令进行“预处理”。这些预处理命令是由 ANSIC统一规定的,但是它不是C语言本身的组成部分,不能直接对它们进行编译。
2.c语言的预处理命令主要包含以下三种:
1.宏定义
2.文件包含
3.条件编译
为了与一般的c语句相区别,这些命令以符号“#”字开头。例如:#define #include
3.宏定义命令
标志:#define
作用:定义符号常量和带参的宏。
分类:不带参数的宏,带参数的宏。
不带参数的宏,定义时的作用:用指定的标识符宏名PI来代替宏体"3.1415926"。
宏替换:在程序编译前会用宏替换程序中出现的所有宏名。
例1:
#include <stdio.h>
#define PI 3.1415926/*不带参的宏定义*/
int main()
{
float i,s,r,v;
printf("input radius:");
scanf("%f",&r);
i=2.0*PI*r;
s=PI*r*r;
v=4.0/3*PI*r*r*r;
printf("i=%10.4f\ns=%10.4f\nv=%10.4f\n",i,s,v);
return 0;
}
说明
1.宏名一般习惯用大写字母表示,以便与变量名相区别,也可用小写字母。宏名不分配占存储空间,变量分配存储空间。
2.宏定义不是C语句,不必在行未加分号。如果加了分号则会连分号一起进行置换。
3.#define命令写在文件开头,作用范围是从定义位置开始到最后一行均有效。但可以用#undef命令终止宏定义的作用域。
例2:在宏定义中可引用已定义的宏名
#include <stdio.h>
#define R 4.0
#define PI 3.1415926
#define L 2*PI*R/*宏体中引用已经定义过的宏名PI和R*/
#define S PI*R*R/*宏体中引用已经定义过的宏名PI和R*/
int main()
{
printf("L=%10.4F\nS==%10.4f\n",L,S);
return 0;
}
宏定义命令
带参数的宏定义作用:不光进行字符串替换,还要进行参数替换。
示例:
#define S(a,b) a*b
area=S(3,2);
带实参的宏替换过程描述,按#define命令行中指定的字符串,从左到右进行置换。,若串中包含宏中的形参(如a、b),,则将程序中相应的实参(可以是常量、变量或表达式)代替形参.若宏体中的字符不是参数的字符( 如a*b中的*号),则保留。
例3.写出运行结果
#include <stdio.h>
#define S(a) 2*a*a/*定义了带参的宏*/
int main()
{
int m;
m=S(5);
printf("m=%d\n",m);
return 0;
}
注意:对带参数宏替换只是将语句中的宏名后面括号内的实参字符串代替#define 命令行中的形参。对带参数的宏替换只是将语句中的宏名后面括号内的实参字符串代替#define命令行中的形参。在宏定义时,在宏体中出现的除了参数以外的字符都会有所保留。
注意:带参数的宏和函数的区别
函数调用要进行参数的传递及函数体内语句的
执行;而带参的宏只是进行简单的字符替换。
函数调用是在程序运行时处理的,会为形参分
配临时的存储单元;而宏替换是在编译前进行,在展开时并不分配内存单元,不进行值的传递处理,也没有“返回值”的概念。
函数要求实参和形参类型一致;而宏名无类型,参数也无类型,只是一个符号代表,替换时代入指定的字符串即可。宏定义时,字符串可以是任何类型的数据。
调用函数只可得到一个返回值,而用宏可以得到几个结果。
例4:带参宏的应用
#include <stdio.h>
#define PI 3.1415926
#define CIRCLE(R,L,S,V) L=2*PI*R; S=PI*R*R;V=4.0/3.0*PI*R*R*R
int main()
{
float r,l,s,v;
scanf("%f",&r);
CIRCLE(r,l,s,v);
printf("r=%6.2f,l=%6.2f,s=%6.2f,v=%6.2f\n",r,l,s,v);
return 0;
}
4.文件包含
格式:
#include<文件名>
#include"文件名"
作用:一个源文件可以将另一个源文件的全部内容包含进来。
例.利用文件包含预处理命令,按照规定格式,输出多个指定变量或表达式的值。分析:源文件中包含的文件中应有输出函数;多个变量,类型、输出格式均有可能不相同,故利用带参宏定义命令做成一个通用格式。完成源文件s.c的编写,其中要包含文件FORM.h。注意,在例1中有两个文件,但并不是各自编译,而是在编译预处理后将头文件FORM.h包含到s.c文件中,得到一个新的源程序,然后对新文件进行编译,得到一个新的目标(.obj)文件。
#include <stdio.h>
#include “FORM.h"
int main()
{ int a=1;
char string[]="ABCDEF" ;
PRINT(5.1,f,3.25);
PRINT(3,d,a);
PRINT(10,s,string);
PRINT(,d,8+2);
return 0;}
#include <stdio.h>
int main()
{ int a=1;
char string[]="ABCDEF" ;
printf("\n%5.1f",(3.25));
printf("\n%3d",(a));
printf("\n%10s",(string));
printf("\n%d",(8+2));
return 0;}
使用文件包含时注意的问题:一个#include命令只能指定一个被包含文件,如果要包含n个文件,要用n个#include命令。如果文件1包含文件2,而在文件2中要用到文件3的内容,则可在文件1中用两个include命令分别包含文件2和文件3,而且文件3应出现在文件2之前,即在file1.c中定义.
5.条件编译。
作用:对部分内容制订编译条件,使其只在满足一定条件才能进行编译。
标志:#ifdef,#ifndef,#if.
形式: #ifdef 标识符
程序段1
#else
程序段2
#endif
例:输入一行字母字符,根据需要设置条件编译,使之能将字母全改为大写输出,或全改为小写字母输出。分析:根据条件判断,若为大写字母,则ASCII码加32,变为小写;若为小写字母,则ASCII码减32,变为大写。
#include <stdio.h>
#define LETTER 1
int main()
{
char str[]="ABdeFgh",c;
int i;
i=0;
while((c=str[i])!='\0')
{
i++;
if(c>='a'&&c<='z') c=c-32;
if(c>='A'&&c<='Z') c=c+32;
printf("%c",c);
}
return 0;
}
- 点赞
- 收藏
- 关注作者
评论(0)