一. #define简介
1. #define命令是宏定义命令,主要在预编译的时候进行字符替换,把宏名用宏体进行替换
2. 预编译的主要工作主要是进行代码文本的替换工作,用于处理#开头的指令,包括#Include、#define、#ifdef、#endif等等,预编译的工作只是纯粹的替换与展开,没有任何的计算功能
二. #define命令的缺陷
1. 无法进行类型检查。宏定义是在编译之前进行的字符替换,因为还没有编译所以不能在编译之前就进行检查类型是否匹配,而只能在编译时候才知道,所以无法进行类型检查
2. 由于优先级的不同,在进行宏定义的时候可能存在副作用。比如#define Add(a,b) a+b,这个时候直接把宏体替换掉的时候可能会存在问题,正确的写法是#define Add(a,b) ((a)+(b))
3. 会导致代码膨胀。由于宏定义是进行文本替换,需要对代码进行展开,因此多处使用宏定义会存在冗余代码
三. 含参数的宏和函数的区别
1. 函数调用的时候首先求出实参表达式的值,然后带入形参。宏定义只是进行简单的字符替换
2. 函数调用过程是在程序运行的时候,它需要分配临时的内存单元。宏展开是在预编译的时候,不需要分配内存单元
3. 函数参数存在类型问题;宏中不存在类型问题,展开的时候带入指定的字符即可
4. 宏展开多次使得源程序会变得很长,而函数调用是不会使源程序变长的
5. 宏展开是不占运行时间的,而函数调用需要占运行时间
四. 宏展开隐藏的问题
下面这个程序
#define Y(n) (4*n)
int main(){
int a = Y(5+1);
printf("%d\n", a);
return 0;
}
输出结果是21,为什么不是24?
因为宏定义的原因Y(5+1) = (4*5+1),这个时候实际上是把n用5+1来替换,所以就得到了21。
五. #define和const的区别
define和const都能够定义常量,define既可以替代常数值,又可以替代表达式,甚至是代码段,但是比较容易出错。const的引入可以增强程序的可读性,使程序的维护与调试变的更加方便。
1. define只是用来进行单纯的文本替换,define常量的生命周期止于编译期,不分配内存空间,它存在于程序代码区,在实际的程序中只是一个常数
const常量存在于程序的常量区,const常量在程序中确实存在,可以被调用和传递
2. const常量是有数据类型的,而define常量没有数据类型
3. 编译器会对const常量进行类型检查,define是在预编译时候进行替换不会进行类型检查
const常量保护程序中的常量不被修改,而且对数据类型也会进行检查,提高了程序的健壮性,所以一般用const来定义常量类型