目录
1.前言
2.文件包含
2.宏定义
2.1 无参数的宏
2.2 带参宏定义
3.条件编译
预处理是指在进行编译的词法扫描和语法分析之前所作的工作。预处理指令指示在程序正式编译前就由编译器进行的操作,可放在程序中任何位置。处理完毕自动进入对源程序的编译。C/C++中的预处理主要包含三种:文件包含、宏定义、条件编译
文件包含命令行的一般形式为:
#include"文件名" 或 #include<文件名>
值得注意的是,
(1)<>表示在包含文件目录中去查找(包含目录是由用户在设置环境时设置的include目录),而不在当前源文件目录去查找;
(2) ""则表示首先在当前源文件目录中查找,若未找到才到包含目录中去查找。
(3)一个include命令只能指定一个被包含文件,若有多个文件要包含,则需用多个include命令。
(4)一个包含文件中可以包含别的包含文件。
C语言程序中广泛的使用宏定义,采用关键字define进行定义,宏只是一种简单的字符串替换,根据是否带参数分为无参和带参。
#define 宏名 一段符号
其中一段符号表示你需要的用宏名来代替的一段符号,在编译预处理时,程序中出现的所有你设定的宏名都将被这段符号代替。
样例:#define ip 114514
表示程序中出现的所有ip都将表示114514。
测试:
#include
#define ip 114514
int main()
{
int a = ip;
printf("%d\n",a);
return 0;
}
结果:
一般我们使用宏定义是为了方便修改和管理代码。
需要注意的是宏定义不作语法检查,只有在编译被宏展开后的源程序才会报错。
测试1:
#include
#define ip 1+2 = 3
int main()
{
int a = 0;
printf("%d\n", a);
return 0;
}
结果:
这里没使用宏,宏没被展开,宏没做语法检查而不报错。
测试2:
#include
#define ip 1+2 = 3
int main()
{
int a = ip;
printf("%d\n", a);
return 0;
}
结果:
#define 宏名(形参表) 字符串
在宏定义中的参数称为形式参数,在宏调用中的参数称为实际参数。
对带参数的宏,在调用中,不仅要宏展开,而且要用实参去代换形参。
样例:#define MULTIPLY_2(x,y) ((x)*(y))
注意:在这个宏中,x和y作为参数在表达式中,应被括号分隔开。也就是说当宏中有表达式时,其内部参数需被括号独立,防止程序出错。
样例:
#include
#define a1(x,y) (x*y)
#define a2(x,y) ((x)*(y))
int main()
{
int a = 1;
int b = 2;
int sum1 = a1(a + b, b);//sum1=(a+b*b)
int sum2 = a2(a + b, b);//sum2=((a+b)*b)
printf("%d %d\n", sum1,sum2);
return 0;
}
结果:
一般情况下,源程序中所有的行都参加编译。但有时希望对其中一部分内容只在满足一定条件才进行编译,也就是对一部分内容指定编译的条件,这就是条件编译。
样例1:
#include
#define a1(x,y) (x*y)
#define a2(x,y) ((x)*(y))
int main()
{
int a = 1;
int b = 2;
int sum1 = a1(a + b, b);
int sum2 = 0;
#ifdef a2 //这里只是检查宏有没有定义,并不检查值
if (a == 1)
{
sum2 = a2(a + b, b);
}
#else
if (a == 2)
{
int sum2 = a2(a + b, b);
}
#endif
{
printf("%d %d\n", sum1,sum2);
}
return 0;
}
结果:
样例2:
#include
#define a1(x,y) (x*y)
//#define a2(x,y) ((x)*(y))
int main()
{
int a = 1;
int b = 2;
int sum1 = a1(a + b, b);
int sum2 = 0;
#ifdef a2 //这里只是检查宏有没有定义,并不检查值
if (a == 1)
{
sum2 = a2(a + b, b);
}
#else
sum2 = sum1;
#endif
{
printf("%d %d\n", sum1,sum2);
}
return 0;
}
结果:
显而易见的,宏有没有定义直接影响了程序运行的结果。
ps:c编译器中,有几个特殊形式的预定义宏需要我们注意。
__FILE__ 宏所在文件的源文件名
__FUNCTION__ 宏所在函数名
__LINE__ 宏所在行的行号
__DATE__ 代码编译的日期
__TIME__ 代码编译的时间
样例:
#include
#define a1(x,y) (x*y)
//#define a2(x,y) ((x)*(y))
int main()
{
int a = 1;
int b = 2;
int sum1 = a1(a + b, b);
int sum2 = 0;
#ifdef a2 //这里只是检查宏有没有定义,并不检查值
if (a == 1)
{
sum2 = a2(a + b, b);
}
#else
sum2 = sum1;
#endif
{
printf("%d %d\n", sum1,sum2);
}
printf("文件名:%s\n", __FILE__);
printf("函数名:%s\n", __FUNCTION__);
printf("行 号:%d\n", __LINE__); //
printf("日 期:%s\n", __DATE__); //
printf("时 间:%s\n", __TIME__); //
return 0;
}
结果: