【C语言】三剑客之《C陷井与缺陷》完整笔记( 四 )


第6章:预处理器
宏定义提供了一种对组成C程序的字符串进行变换的手段(即什么代表什么) , 而并不作用于程序中的对象
6.1 宏中空格
如下例子 , 是f代表(x)((x)-1) , 不是f(x)代表((x)-1)
#define f (x) ((x)-1)
6.2 宏不是函数
#define abs(x)x>0?x:-x
如果你这样调用宏abs(a-b) , 会被展开为a-b>0?a-b:-a-b , 他不会像函数一样 , 计算参数(a-b)的值然后传入 , 所以定义宏的时候 , 每个变量都要有老大哥“()”:
#define abs(x)(x)>0?(x):-(x)
#define abs(a , b)(a)>(b)?(a):(b)x[0] = 2;x[1] = 5; x[2] = 1;biggest = x[0];while(i
我们再展开: = ()>(x[i++])?():(x[i++]),i自加了两次 , 所以后果就是x[1]比x[2]大 , 却输出了x[3] , 贼气
6.3和6.4讲解了宏定义不是语句也不是类型定义 , 问题大同小异 , 都是因为原本的宏只做替换不做计算 , 展开后语句结合就错乱了 , 别用太复杂的宏 , 除非这个东西被反复用到
第7章:可移植性缺陷
直接举例:
void printnum(long n,void(*p)()){if(n<0){(*P) ('-');//打印负号n = -n;}if(n>=10)printnum(n/10 , P);(*p) ((int)(n%10)+'0');}
这里偷懒了 , 没看步骤不知道有哪些问题 , 有空再回头看 , 作者是这样解决的:
void printnum(long n,void(*p)()){long q;int r;q = n/10;r = n%10;if(r>0){r -=10;q++;}if(n <= -10)printnum(q , P);(*p) ("0123456789"[-r]);}
好 , 这本书我们就看完了!