Hightlight
1. 宏
1.1 ifdef
2.2 解决重复引入头文件问题
2.3 C语言中预先定义好的一些宏
2.4 带参宏
2.4.1 宏函数问题1: 参数不带括号情况
2.4.2 宏函数问题2: 式子不带括号情况
2.4.3 宏函数问题3: ++ —— 赋值
2.4.4 宏函数问题4: 无类型检查
2.4.5 宏函数里井号的作用
1. 宏
1.1 ifdef
#ifndef H //如果没定义过H 那就定义H
例如
21 #ifdef H 22 #ifndef H 23 #define H "123" 24 #endif
NOTE: gcc-E 可以看到预处理之后的效果
2.2 解决重复引入头文件问题
c语言中头文件定义模板: 确保其中的内容不会被定义两次, 插入多份也没关系
#ifndef VX #define VX 1 int x=3; #endif
-->参考stdio.h头文件 /usr/include/stdio.h头文件
按照这种做法 下面例子编译通过
1 /* header.h */ 2 #ifndef HEADER_H 3 #define HEADER_H 1 4 struct s {}; 5 typedef struct s s; 6 #endif //HEADER_H
1 /* header.c */ 2 3 #include <stdio.h> 4 #include "header.h" 5 #include "header.h" 6 //#include "func.h" 7 //#define Vx 1 8 9 #ifndef VX 10 #define VX 1 11 int x=2; 12 #endif 13 14 #ifndef VX 15 int x=3; 16 #endif 17 18 int main() 19 { 20 s a; 21 printf("%d\n",x); 22 return 0; 23 }
2.3 C语言中预先定义好的一些宏
1 #include <stdio.h> 2 int main() 3 { 4 __FILE__ 5 __LINE__ 6 __DATE__ 7 __TIME__ 8 __STDC__ 9 return 0; 10 }
2.4 带参宏(宏函数)
基本的宏函数
1 #include <stdio.h> 2 3 #define SWAP(T,x,y){T t=x;x=y;y=t;} 4 5 int main() 6 { 7 int a =10,b=20; 8 double c = 12.3, d=45.6; 9 SWAP(int, a,b); 10 SWAP(double, c, d); 11 12 printf("a=%d , b=%d\n",a,b); 13 printf("c=%g,d=%g\n",c,d); 14 15 return 0; 16 }
预编译后的效果
int main() { int a =10,b=20; double c = 12.3, d=45.6; {int t=a;a=b;b=t;}; {double t=c;c=d;d=t;}; printf("a=%d , b=%d\n",a,b); printf("c=%g,d=%g\n",c,d); return 0; }
宏函数问题-----面积计算的结果不对
1 #include <stdio.h> 2 3 #define SWAP(T,x,y){T t=x;x=y;y=t;} 4 #define MAX(x,y) x<y?y:x 5 #define PI 3.14159 6 #define AREA(r) PI*r*r 7 int main() 8 { 9 int a =10,b=20; 10 double c = 12.3, d=45.6; 11 SWAP(int, a,b); 12 SWAP(double, c, d); 13 14 printf("a=%d , b=%d\n",a,b); 15 printf("c=%g,d=%g\n",c,d); 16 17 printf("%d\n",MAX(a,b)); 18 printf("%g\n",AREA(a+b)); 19 return 0; 20 }
面积计算的结果:
查看预编译进行debug
解决办法 带参数的宏永远要对宏的参数加括号!
6 #define AREA(r) PI*(r)*(r)
预编译的结果:
printf("%g\n",3.14159*(a+b)*(a+b));
宏函数问题2-----求和不一样
1 #include <stdio.h> 2 3 #define SWAP(T,x,y){T t=x;x=y;y=t;} 4 #define MAX(x,y) x<y?y:x 5 #define PI 3.14159 6 #define AREA(r) PI*(r)*(r) 7 8 int main() 9 { 10 int a =10,b=20; 11 double c = 12.3, d=45.6; 12 int e=50, f=60; 13 14 SWAP(int, a,b); 15 SWAP(double, c, d); 16 17 printf("a=%d , b=%d\n",a,b); 18 printf("c=%g,d=%g\n",c,d); 19 20 printf("%d\n",MAX(a,b)+MAX(e,f)); 21 printf("%g\n",AREA(a+b)); 22 return 0; 23 }
和为50, 预编译debug发现:
printf("%d\n",a<b?b:a+e<f?f:e);
在写宏函数时候整个式子要用括号括起来避免冲突
宏函数问题3: 带++ ——和赋值的式子 作为宏参数
printf("%d\n",MAX(++a,++b)); 执行结果:22 预编译结果: printf("%d\n",(++a<++b?++b:++a));
调用宏函数时候不要使用带++ ——和赋值的式子 作为宏参数
宏函数问题4: 没有类型检查
宏函数里井号的作用:
1). 单井号:把参数编程对应的字符串
#define STR(x) puts(#x) STR(hello); 打印出来hello
2). 双井号:拼接标示符
1 #include <stdio.h> 2 3 #define SWAP(T,x,y){T t=x;x=y;y=t;} 4 #define MAX(x,y) (x<y?y:x) 5 #define PI 3.14159 6 #define AREA(r) PI*(r)*(r) 7 #define STR(x) puts(#x) 8 9 void welcomestudent(){printf("welcome every body.\n");} 10 void welcometeacher(){printf("welcome all teacher\n");} 11 #define welcome(who) welcome##who() 12 13 int main() 14 { 15 int a =10,b=20; 16 double c = 12.3, d=45.6; 17 int e=50, f=60; 18 19 SWAP(int, a,b); 20 SWAP(double, c, d); 21 22 printf("a=%d , b=%d\n",a,b); 23 printf("c=%g,d=%g\n",c,d); 24 25 printf("%d\n",MAX(a,b)+MAX(e,f)); 26 printf("%g\n",AREA(a+b)); 27 printf("%d\n",MAX(++a,++b)); 28 29 STR(hello); 30 31 welcome(student); 32 welcome(teacher); 33 return 0; 34 }
练习: 写一个ISLEAP(Y)的宏函数 判断闰年