目录
一,#define的声明格式:
二,#define宏的作用是为了完成替换
#define的替换规则:
三,#define使用时常犯的错误
四,宏与函数的比较
4.1,什么时候使用宏?
4.1,使用宏的好处与坏处
4.3宏的奇怪用法
#define name( parament-list ) stuff
关于#define格式需要注意的几个点:
1.在stuff后面不能有冒号
2.name要和左圆括号紧贴在一起
:使用#define定义一个 求两者间较大值的宏:
#define MAX(a,b) a>b?a:b
1. 在调用宏时,首先对参数进行检查,看看是否包含任何由 #define 定义的符号。如果是,它们首先被替换。2. 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换。3. 最后,再次对结果文件进行扫描,看看它是否包含任何由 #define 定义的符号。如果是,就重复上述处理过程。
比如以下代码:
#define MAX(a,b) a>b?a:b
#include
int main() {
int a = 10;
int b = 5;
printf("%d\n", MAX(a, b));
}
在程序预处理的过程中就会变成这样:
#define MAX(a,b) a>b?a:b
#include
int main() {
int a = 10;
int b = 5;
printf("%d\n",a>b?a:b);//MAX(a,b)直接被替换掉
}
这也就解释了为什么在宏定义语句的末尾为什么不能加 ;(分号),假如我在宏定义后面加了分号:
#define MAX(a,b) a>b?a:b;
那在替换过程中,MAX(a,b)就会被替换成这样:
a>b?a:b;
#define MAX(a,b) a>b?a:b
#include
int main() {
int a = 10;
int b = 5;
printf("%d\n",a>b?a:b;);//明显就是一个错误的代码
}
所以我们便不能在宏定义后面随意加上;(冒号)。
3.1不加括号:
#define MUL(a,b) a*b //参数不加括号
现在我让a=2+1,b=2+1代入下列代码中:
#include
#define MUL(a,b) a*b
int main() {
int c = MUL(2+1, 2+1);
printf("%d\n", c);
return 0;
}
结果:5
但是我们都知道3*3等于9,所以这个代码为什么会错呢?
原因其实很简单,因为宏会直接替换,也就是宏其实是不会计算的。 所以这段宏就会被替换成这样:
#define MUL(2+1,2+1) 2+1*2+1//c=2+1*2+1=5
int main() {
int c = MUL(2+1, 2+1);
printf("%d\n", c);//c=5
return 0;
}
所以结果就变成5了。
在这里做一个小小的改动:
#include
#define MUL(a,b) (a)*(b)//加两个括号
int main() {
int c = MUL(2+1, 2+1);
printf("%d\n", c);
return 0;
}
于是宏替换就会变成这个样子:
#define MUL(2+1,2+1) (2+1)*(2+1)//c=(2+1)*(2+1)=9
int main() {
int c = MUL(2+1, 2+1);
printf("%d\n", c);//c=5
return 0;
}
输出:9
但是仅仅做到这样有时候是不保险的:
比如:
:
#define MUL(a,b) (a)+(b)
#define MUL(a,b) (a)+(b)
int main() {
int c = 10*MUL(3, 3);//计算的值应该是60
printf("%d\n", c);
return 0;
}
但是:
输出:33
因为在这里宏替换以后,宏会变成这样:
#define MUL(a,b) (3)+(3)
int main() {
int c = 10*(3)+(3);//相当于10*3+3==33
printf("%d\n", c);
return 0;
}
在这里就有一个解决方案:
#define MUL(a,b) ((a)+(b))//再加一个大括号
int main() {
int c = 10*MUL(3, 3);//计算的值应该是60
printf("%d\n", c);
return 0;
}
这样就可以得到我们想要的60了。
在这里我们有一个基本的常识:
1.实现简单的功能时使用宏。
比如:求两个数的较大值
#define MAX(a,b) ((a)>(b)?(a):(b))
2.实现复杂功能时用函数。
好处:
1.宏在小型程序中执行的时候更加有效率
2.宏是没有类型的,所以调用的时候更加方便
坏处:
1.无法调试
2. 每次使用宏的时候,一份宏定义的代码将插入到程序中。除非宏比较短,否则可能大幅度增加程序 的长度。
比如使用 malloc这个函数:
正常使用:
#include
#include int main() { int* arr = (int*)malloc(20); if (*arr == NULL) { perror("malloc:"); return; } //使用 //关闭 free(arr); arr = NULL; return 0; }
使用宏:
先定义宏:
#define MALLOC(type,nums) (type)malloc(nums*sizeof(type))
然后就可以这样使用:
#include
#include
#define MALLOC(type,nums) (type)malloc(nums*sizeof(type))
int main() {
int* arr = MALLOC(int*,20);
if (*arr == NULL) {
perror("malloc:");
return;
}
//使用
//关闭
free(arr);
arr = NULL;
return 0;
}
今天分享完毕。。。。