宏的使用
#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏(define macro)。
宏的申明方式:#define name( parament-list ) stuff (注释:parament-list 是一个由逗号隔开的符号表,它们可能出现在stuff中)
#define df(x) x*x
参数列表的左括号必须与name紧邻。
如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分。
#define df(x) x*x
int main()
{
int a = 5;
printf("%d",df(a));
return 0;
}
这个宏接收一个参数 x .
置于程序中,预处理器就会用下面这个表达式替换上面的表达式:
#define df(x) x*x
int main()
{
int a = 5;
printf("%d",a*a);
return 0;
}
需要注意宏存在一个问题
#define df(x) x*x
int main()
{
int a = 5;
printf("%d",df(a+1));
return 0;
}
会变成如下
printf("%d",a+1*a+1);
在宏定义上加上两个括号,这个问题便轻松的解决了:
#define df(x) (x)*(x)
int main()
{
int a = 5;
printf("%d",df(a+1));
//printf("%d",(a+1)*(a+1));
return 0;
}
这样预处理之后就产生了预期的效果
这里还有一个宏定义:
#define df(x) (x)+(x)
int main()
{
int a = 5;
printf("%d",10*df(a));
//printf("%d",10*(5)+(5)); 结果为错
return 0;
}
我们还需要加上一个括号使宏先得出结果后再使用
#define df(x) ((x)+(x))
int main()
{
int a = 5;
printf("%d",10*df(a));
//printf("%d",10*((5)+(5)));
//printf("%d",10*(10));
return 0;
}
宏和函数对比
宏通常被应用于执行简单的运算
比如在两个数中找出较大的一个
#define df(x,y) ((x) > (y)? (x) : (y))
那为什么不用函数来完成这个任务?
- 用于调用函数和从函数返回的代码可能比实际执行这个小型计算工作所需要的时间更多。
所以宏比函数在程序的规模和速度方面更胜一筹。 - 更为重要的是函数的参数必须声明为特定的类型。
所以函数只能在类型合适的表达式上使用。反之这个宏怎可以适用于整形、长整型、浮点型等可以
用于>来比较的类型。
宏是类型无关的。
宏的缺点:
3. 每次使用宏的时候,一份宏定义的代码将插入到程序中。除非宏比较短,否则可能大幅度增加程序
的长度。
4. 宏是没法调试的。
5. 宏由于类型无关,也就不够严谨。
6. 宏可能会带来运算符优先级的问题,导致程容易出现错。.
宏有时候可以做函数做不到的事情
#define MALLOC(num,type) (type*)malloc(num*sizeof(type))
int main()
{
MALLOC(10,int);
//预处理器替换之后:
(int *)malloc(10 * sizeof(int));
return 0;
}
宏和函数的一个对比
| #define定义宏 | 函数 |
|---|---|
| 每次使用时,宏代码都会被插入到程序中。除了非常小的宏之外,程序的长度会大幅度增长 | 函数代码只出现于一个地方;每次使用这个函数时,都调用那个地方的同一份代码 |
| 更快 | 存在在函数的调用和返回的额外开销,所以相对慢一些 |
| 宏参数的求值是在所有周围表达式的上下文环境里,除非加上括号,否则邻近操作符的优先级可能会产生不可预料的后果,所以建议宏在书写的时候多些括号。 | 函数参数只在函数调用的时候求值一次,它的结果值传递给函数。表达式的求值结果更容易预测。 |
| 参数可能被替换到宏体中的多个位置,所以带有副作用的参数求值可能会产生不可预料的结果。 | 函数参数只在传参的时候求值一次,结果更容易控制 |
| 宏的参数与类型无关,只要对参数的操作是合法的,它就可以使用于任何参数类型。 | 函数的参数是与类型有关的,如果参数的类型不同,就需要不同的函数,即使他们执行的任务是相同的。 |
| 宏是不方便调试的 | 函数是可以逐语句调试的 |
| 宏是不能递归的 | 函数是可以递归的 |
3万+

被折叠的 条评论
为什么被折叠?



