~Linux C_16_预处理
====预处理====
gcc -E main.c
//只有链接处理,没有出错检查
====函数式宏定义====
1.效率问题
#include<stdio.h> #define MAX(a, b) ((a)>(b)?(a):(b)) //*** int a[] = { 9, 3, 5, 2, 1, 0, 8, 7, 6, 4 }; int max(int n) { return n == 0 ? a[0] : MAX(a[n], max(n-1)); } int main(void) { max(9); return 0; } 宏展开后: int max(int n) { return n == 0 ? a[0] : ((a[n])>(max(n-1))?(a[n]):(max(n-1))); }
2.函数代换
do{...}while(0)
3.宏的变换
#define X 3 ... /* X is 3 */ #undef X //到此为止,取消该宏的定义! ... /* X has no definition */ #define X 2 ... /* X is 2 */
==== 内联函数 ====
inline关键字告诉编译器,这个函数的调用要尽可能快,可以当普通的函数调用实现,也可以用宏展开的办法实现。
#include<stdio.h> inline int MAX (int a, int b) //内联函数定义 { return a > b? a : b; } int a[] = { 9, 3, 5, 2, 1, 0, 8, 7, 6, 4 }; int max(int n) { return n == 0 ? a[0] : MAX(a[n], max(n-1)); } int main(void) { max(9); return 0; }
总结:没有call指令调用MAX函数,MAX函数的指令是内联在max函数中的,由于源代码和指令的次序无法对应,max和MAX函数的源代码也交错在一起显示。同时要也说明:函数的调用是个比较耗时间的过程,内联可以简化此消耗。
==== # and ## ====
1. #define STR(s) #s //形参s是个字符串 STR(hello world) ====> "hello world"
2. #define CONNECT(a, b) a##b //字符串的连接作用 CONNECT(tang,bing) ====> "tangbing"
3. #define showlist(...) printf(#__VA_ARGS__) //这里会自动的在...的位置上默认为字符串的内容,然后再加上字符串双引号。 #define report(test, ...) ((test)?printf(#test): printf(__VA_ARGS__)) //主要就是: ... 和 __VA_ARGS__之间的对应关系 showlist(The first, second, and third items.); report(x>y, "x is %d but y is %d", x, y); //这里有了字符串的双引号,所以不需要在_VA_ARGS__之前加上#号。 ====> printf("The first, second, and third items."); ((x>y)?printf("x>y"): printf("x is %d but y is %d", x, y));
4. #define FOO(a, ...) a##__VA_ARGS__ FOO(1) //可变参数部分传了个空 FOO(1,2,3,) //可变参数部分传了三个参数,第三个是空参数
5. #define DEBUGP(format, ...) printk(format, ## __VA_ARGS__) DEBUGP("tangbing", 1); DEBUGP("tangbing"); //这里##号把之前的逗号给吃掉了 ====> printk("tangbing", 1); printk("tangbing"); //确实是吃掉了
6. #if MACHINE == 68000 int x; #elif MACHINE == 8086 long x; #else /* all others */ #error UNKNOWN TARGET MACHINE #endif //有点像switch的结构,条件是:宏是否定义; 常用于平台的移植。