宏定义的本质是在预处理时,对定义部分进行原封不动的替换。
#define M 10
#define N M 是可行的
#define N M
#define M 10 不可行
宏定义是有顺序的,宏定义可以从上到下进行嵌套。
代参宏:
#define x(a,b) (a+b)
宏名为x,参数为a、b,替换为a+b。代参宏的公式一定要注意括号,按照上面的代参宏进行计算,若不在(a+b)部分加入括号而是写为#define x(a,b) a+b可能会出现如下情况:
int a1=3*x(a,b)=>a1=3*a+b
这样的情况下就会出现3*a先结合的情况。所以代参宏一定要注意括号的情况,严格情况下,就连(a+b)的部分也要加入括号:#define x(a,b) ((a)+(b)),避免出现嵌套宏出现如上情况:
#define MAX(a,b) (((a)>(b))?(a):(b))
用宏定义计算一年多少秒:
#define SEC_PER_YEAR (365*24*60*60) 这样的计算是错误的,因为计算的数据已经超出了int的范围
#define SEC_PER_YEAR (365*24*60*60UL) 将数据转为无符号长整型
如果写为
#define SEC_PER_YEAR (365*24*60*60)UL 在预编译时候不会出错,但编译时会出现错误。
代参宏与函数的区别:代参宏在预编译时进行处理、替换、展开,而函数是在调用时进行跳转。
PS:宏定义不会进行参数类型检查。如果希望进行静态类型检查,要使用内联函数(inline),内联函数本质上是函数,所以会进行静态类型检查,本质上又与代参宏相同在原地展开。当函数很短,又希望进行参数类型检查、低开销、多次使用,非常适合使用内联函数。
值得注意的是宏定义不会区分“重载”问题使用#undef时注意以下情况:
#define DEBUG (a)
#undef DEBUG 注销DEBUG定义是有效的
#define DEBUG (a)
#undef DEBUG (a) 会报warning 条件编译不在意宏名后面的内容
#ifdef宏:
#define DEBUG (a)
#ifdef DEBUG 是否存在名DEBUG的宏,当前情况为存在
#define DEBUG_1
#ifdef DEBUG 当前情况为不存在名为DEBUG名称的宏