C语言-宏定义与使用分析
1、C语言中的宏定义
#define是预处理器处理的单元实体之—
#define定义的宏可以出现在程序的任意位置
#define定义之后的代码都可以使用这个宏
2、定义宏常量
#define定义的宏常量可以直接使用
#define定义的宏常量本质为字面量
下面的宏常量定义正确吗?
1 #define ERROR -1 2 3 #define PATHl "D:\test\test.c" 4 5 #define PATH2 D:\test\test.c 6 7 #define PATH3 D:\test\ 8 test.c
3、实例分析
宏定义分析 21-1.c
1 #define ERROR -1 2 #define PATH1 "D:\test\test.c" 3 #define PATH2 D:\test\test.c 4 #define PATH3 D:\test\ 5 test.c 6 7 int main() 8 { 9 int err = ERROR; 10 char* p1 = PATH1; 11 char* p2 = PATH2; 12 char* p3 = PATH3; 13 }
预处理器不会进行语法检查只是简单的文本替换,即这些宏定义都正确!!但编译器会报错!!
4、宏定义表达式
#define表达式的使用类似函数调用
#define表达式可以比函数更强大
#define表达式比函数更容易出错
下面的宏表达式定义正确吗?
1 #define _SUM_(a, b) (a) + (b) 2 3 #define _MIN_(a, b) ((a) < (b) ? (a) : (b)) 4 5 #define _DIM_(a) sizeof(a)/sizeof(*a)
5、实例分析
宏表达式分析 21-2.c
1 #include <stdio.h> 2 3 #define _SUM_(a, b) (a) + (b) 4 #define _MIN_(a, b) ((a) < (b) ? (a) : (b)) 5 #define _DIM_(a) sizeof(a)/sizeof(*a) 6 7 8 int main() 9 { 10 int a = 1; 11 int b = 2; 12 int c[4] = {0}; 13 14 int s1 = _SUM_(a, b); 15 int s2 = _SUM_(a, b) * _SUM_(a, b); 16 int m = _MIN_(a++, b); 17 int d = _DIM_(c); 18 19 printf("s1 = %d\n", s1); 20 printf("s2 = %d\n", s2); 21 printf("m = %d\n", m); 22 printf("d = %d\n", d); 23 24 return 0; 25 }
6、宏表达式与函数的对比
宏表达式被预处理器处理,编译器不知道宏表达式的存在
宏表达式用“实参“完全替代形参,不进行任何运算
宏表达式没有任何的“调用”开销
宏表达式中不能出现递归定义
1 #define _SUM_(n) ((n > 0) ? (_SUM_(n-1) + n): 0) //error 2 3 int s = _SUM_(10);
7、有趣的问题
宏定义的常量或表达式是否有作用域限制?
下面的程序合法吗?
1 void def() 2 { 3 #define PI 3.1415926 4 #define AREA(r) r*r*PI 5 } 6 7 double area(double r) 8 { 9 return AREA(r); 10 }
8、实例分析
宏的作用域分析 21-3.c
1 #include <stdio.h> 2 3 void def() 4 { 5 #define PI 3.1415926 6 #define AREA(r) r * r * PI 7 } 8 9 double area(double r) 10 { 11 return AREA(r); 12 } 13 14 int main() 15 { 16 double r = area(5); 17 18 printf("PI = %f\n", PI); 19 printf("d = 5; a = %f\n", r); 20 21 return 0; 22 }
9、强大的内置宏
__LINE__ 表示当前行号,整型值
__FILE__ 表示当前文件名,字符串类型
__DATE__ 编译的日期,字符串类型
__TIME__ 编译的时间,字符串类型
__STDC__ 预定义的宏
10、实例分析
宏使用综合示例 21-4.c
1 #include <stdio.h> 2 #include <malloc.h> 3 4 #define MALLOC(type, x) (type*)malloc(sizeof(type)*x) 5 6 #define FREE(p) (free(p), p=NULL) 7 8 #define LOG(s) printf("[%s] {%s:%d} %s \n", __DATE__, __FILE__, __LINE__, s) 9 10 #define FOREACH(i, m) for(i=0; i<m; i++) 11 #define BEGIN { 12 #define END } 13 14 int main() 15 { 16 int x = 0; 17 int* p = MALLOC(int, 5); 18 19 LOG("Begin to run main code..."); 20 21 FOREACH(x, 5) 22 BEGIN 23 p[x] = x; 24 END 25 26 FOREACH(x, 5) 27 BEGIN 28 printf("%d\n", p[x]); 29 END 30 31 FREE(p); 32 33 LOG("End"); 34 35 return 0; 36 }
11、小结
预处理器直接对宏进行文本替换
宏使用时的参数不会进行求值和运算
预处理器不会对宏定义进行语法检查
宏定义时出现的语法错误只能被编译器检测
宏定义的效率高于函数调用
宏的使用会带来—定的副作用