# 9. 预处理器
1. #include,#ifdef,#ifndef
- 常见就不用强调了
2. #if,#elif,#else,#endif
- 和if else 差不多,也是后面跟判断条件
3. #define
```
不推荐使用
若定义变量,可以用const
若想用宏函数,可以用内联
若想定义类型,可以用typedef
还有一些加 ## 的骚操作,,,感觉不是很必要,需要的时候再看吧
```
4. #undef
- 取消宏
5. #line和#error
```
1. 预定义宏有 __FILE__,__DATE__,__LINE__,__TIME__。字面意思
2. #line 可以改变__FILE__,__LINE__
3. #error 可以在编译期报错,放在#if等里面
```
6. #pragma
- 编译器设置,例如可以改变struct的对齐字节数
# 10. C库
1. 数学库 math.h
2. 断言库 assert.h
- 调试的时候用
3. string.h 中的memcpy(dest,src,n)和memmove(dest,src,n)的区别
```
传入参数的类别不同,memcpy假定两个字符串没有重叠,用register关键字声明
memmove没有这个限制,所以感觉memmove比较好用
```
4. 通用工具库
```
1. qsort(s1,s2,mycompare);
- 自己写比较函数
2. exit()
- 退出
3. atexit(函数名)
- 在exit执行前,退出前执行某个函数,若注册多个函数,是按照栈的方式注册的,即后面注册的先执行。
```
# 11. 各种小技巧
### 1. 逗号
- 在C语言中,多个表达式可以用逗号分开,其中用逗号分开的表达式的值分别结算,但整个表达式的值是最后一个表达式的值。
- 假设b=2,c=7,d=5,
```
a1=(++b,c--,d+3);
a2=++b,c--,d+3;
```
- 对于第一行代码,有三个表达式,用逗号分开,所以最终的值应该是最后一个表达式的值,也就是d+3,为8,所以a1=8。
- 对于第二行代码,那么也是有三个表达式,这时的三个表达式为a2=++b、c--、d+3,(这是因为赋值运算符比逗号运算符优先级高)所以最终表达式的值虽然也为8,但a2=3。
- 注意:逗号运算的结合性是从左至右,完毕之后整个表达式的值是最后一个表达式的值。
- 例子:int a[2],x=2,y=5;
a[0]=(x+3,y++,x++);那么最终结果是:a[0]=2 x=3 y=6;
为何a[0]=2:因为(x++)是运算之后再自加
a[1]=(x++,x+3,x+7);那么最终结果是:a[1]=11 ,x=4
逗号运算是从左至右,所以先算x++,x从而变成4了,然后a[1]=4+7=11;