#define 关键字有两个作用,一个是定义标识符,第二个是定义宏。
1. 定义标识符
//#define name stuff
#define MYINT int
建议不要在define定义的标识符里加分号。
2. 定义宏
#define 机制有一个规定,允许把参数替换到文本中,这种实现通常叫做宏或定义宏。
//#define name(parament-list) stuff
#define MAX ((a)>(b)?(a)(b))
int a = MAX(11+2,11-2);//int a = ((11+2)>(11-2)?(11+2):(11-2));
- 宏定义永远不要吝啬括号,防止因为优先级的问题导致出现不可思议的后果。
- 宏不能实现递归。
- 宏只文本替换,并不简化计算。
- 字符串中的内容不会发生宏替换。
#define X 100
printf("X");//不会宏替换#和##
2.1 宏和函数对比
- 宏没有类型检查
没有类型检查是宏的一大特点(但同时也是不安全的隐患),可以完成很多函数不可能做到的功能。
#define MALLOC(n,type)\
(type*)malloc(n*sizeof(type))
- 宏没有函数的调用和返回等额外开销,效率更高,
当逻辑复杂并且代码量巨大时,调用和返回的开销和运算的时间相比微乎其微,可以省略
宏单纯只是文本替换,不能进行调试,很致命
宏可能会使代码长度增长
- 函数的参数如果是一个表达式,会计算出表达式的结果传入参数
宏的参数如果是一个表达式,只会文本替换,不会进行计算
总结:各有千秋,小代码量使用宏,大代码量使用函数,C++中摈弃宏这一概念,使用内联,基于优缺点,最好不要使用宏
2.2 带有副作用的宏参数
int a = 10;int b = 0;
b = a+1;
b = a++;//带有副作用的表达式,使a发生改变
不要给宏参数传入带有副作用的参数
2.3 命名约定
宏:全部大写
函数: 不全部大写
例外
//getchar()由库函数实现还是由宏实现是编译器决定的
#define getchar() getc()
#undef name //取消宏标识符name的定义