C 陷阱与缺陷学习 笔记 —— 六、预处理器
宏:只对程序其文本作用[*]注意宏中的空格(区分的关键) #define Func(x) (x*2+3)
例如:#defineF (x)((x)-1)
[*]注意括号的安全使用
例如:
#define f(x)(x*x)
替换结果为:e=(a+b*a+b)*(c+d*c+d) = 5*34=170
#define f(x) x*x
替换结果为:e=a+b*a+b*c+d*c+d=1+2+12+24+4=43
#define f(x) ( (x)*(x) )
替换结果为:e=( (a+b)*(a+b)*(c+d)*(c+d) )=3*3*10*10=900
[*]宏不是函数 #defineabs(x)x>0?x:-x
例如: abs(a-b) <---> a-b>0?a-b:-a-b ERROR
所以每个元 都要加括号
#define abs(x) ( (x) >0 ? (x) : (-(x)) )
例如:abs(u8Data[i++])引入可变元之后导致展开的各项都做了重复操作 ERROR
[*]宏不是语句
例如:#defineassert(e) if(!e)assert_erroe(__FILE__, __LINE__)
if(x>0 && y>0)
assert(x>y);
else
assert(y>x);
ERROR
if(x>0 && y>0)
if(!(x>y))
assert_erroe(__FILE__, __LINE__);
else
if(!(y>x))
assert_erroe(__FILE__, __LINE__);
例如:#defineassert(e) \
{if(!e)assert_erroe(__FILE__, __LINE__); }
if(x>0 && y>0)
assert(x>y);
else
assert(y>x);
ERROR
if(x>0 && y>0)
{ if(!(x>y))
assert_erroe(__FILE__, __LINE__);
};
else
{
if(!(y>x))
assert_erroe(__FILE__, __LINE__);
};
解决办法:
1- 重新定义为一个函数
2- #define assert(e) \
( (void) ( (e) || assert_error(__FILE__, __LINE__) ) )
这实际上是利用|| 运算符 对两侧的操作数依次求值的性质:
如果e为真则符号右侧的表达式未进行运算就得出TRUE的结论;
如果e为假则符号右侧的表达式进行运算调用assert_error;
void---强制无类型转换,告诉编译器不要waring!
[*]宏不是类型定义
注:与typedef的区别
#defineT1struct foo *
typedef struct foo *T2;
T1 a,b; <!=> T2 a,b
struct foo * a,b; <!=> struct foo * a;struct foo * b;
页:
[1]