C语言中的宏定义:
定义宏常量:
就宏定义来说,这是正确的,预处理器可以编译过。 但是就真正的编译来说,这是错误的,真正的编译会有语法错误。
示例程序:
1 #define ERROR -1 2 #define PATH1 "D: est est.c" 3 #define PATH2 D: est est.c 4 #define PATH3 D: est 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 }
执行预处理,gcc -E test.c -o test.i,预处理器处理之后结果如下:
预处理器进行直接的文本替换,是不会进行语法检查的。第4行最后一个会被认为是接续符,将第5行接到第4行。
再继续执行编译的话,16,17行会报错。
宏常量和const常量是不同的,const常量本质是变量,要占用内存空间,而define出来的宏是个字面量,不会占用内存空间。
宏定义表达式:
在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 ", s1); 20 // printf("s2 = %d ", s2); 21 // printf("m = %d ", m); 22 // printf("d = %d ", d); 23 24 return 0; 25 }
预处理结果如下:
打开printf打印行,运行结果如下:
程序的输出并不是我们的预期,可见宏代码块的副作用出来了。
第17行真正求得了数组的大小。
宏表达式与函数对比:
宏定义的常量或表达式是否有作用域的限制?
示例程序:
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 ", PI); 19 // printf("d = 5; a = %f ", r); 20 21 return 0; 22 }
编译结果如下:
预处理没有报错,这说明对于宏而言是没有作用域限制的。
作用域的概念是针对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 ", __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 ", p[x]); 29 END 30 31 FREE(p); 32 33 LOG("End"); 34 35 return 0; 36 }
上述程序中定义的宏是无法用函数来取代的。
运行结果如下:
小结: