宏定义往往有三种类型:
第一种:定义符号常量
#define PI 3.1415926
#define MAX_N 10000
第二种:定义傻瓜表达式
#define MAX(a,b) (a)>(b) ? (a) : (b)
#define S(a,b) a*b
第三种:定义代码段
#define P(a) {\
printf("%d\n",a);\
}
宏定义到底在干什么呢?
要知道一个程序从 .c 文件编译成 源程序(可执行程序) 的过程中,首先会有一个预处理过程,什么是预处理呢?简单来说就在执行程序之前所作的准备工作,例如函数库的调用,宏定义命令的执行,我们主要来讲宏定义。
在预处理阶段,所有的宏定义命令(上面三种),都会先一步执行,执行结果就是将程序源码中的宏定义替换成所对应的代码。之后才会开始进行正常的编译。
在编译后,会生成对象文件(.o或.obj,与操作系统有关)。最后执行链接,将对象文件打包,生成可执行文件。
在第一类宏定义中,宏定义的作用就是将PI替换为3.1415926,将MAX_N替换为10000。即进行字符的替换。
在第二类宏定义中,我们将其称作傻瓜表达式,原因在于它将MAX(a,b)仅仅替换为了(a)>(b) ? (a) : (b),将S(a,b)替换为a*b,举个例子:
#include <stdio.h>
#include <math.h>
#define S(a,b) a*b
int main(){
int a = S(2,3);
int b = S(2 + 3, 4 + 5);
printf("%d %d", a, b);
return 0;
}
输出结果为:
6 19 //有点傻,只是单纯的做了替换
因为S(2 + 3, 4 + 5)被替换为了2 + 3*4 + 5,根据优先级的运算,该式子的结果为19.
关于第三类表达式,我们不会经常使用,但功能仍是相同的,即替换P(a)为后面的代码段。值得一提的是,当宏定义需要换行时,需要在宏的末尾加一个符号"\"。
接下来讲一讲预定义宏:
预定义的宏即标准库中已经实现好的宏,例如:
__DATE__ 日期: Mmm dd yyyy(最后一次编译的日期)
__TIME__ 时间: hh:mm:ss(最后一次编译的时间)
__LINE__ 行号
__FILE__ 文件名
__func__ 函数名/非标准
__FUNC__ 函数名/非标准
__PRETTY_FUNCTION 更详细的函数信息/非标准
在不同的操着系统中,有些预定义宏并不在函数库中,因此有些宏是非标准的。