宏
概要 :C语言中宏是非常见的 ,宏的实质是代码的简单替换。下来从以下几个方面来具体说明 :
(一 ) 宏调用与函数调用的区别 :
1:当函数被调用时 ,相当于发生了一个中断 ,程序先将自己的地址压栈然后转到被调函数的地址的入口点去执行被调函数 ,完成后返回再回去接着执行主调程序;而比起宏来说这样既费时间又费空间 (如果是调用宏直接将代码展开 ,替换执行就可以了 ),下面举例子说明 :一个返回最小值的函数调用和宏调用 :
/*先是函数定义 */
int max(int x,int y)
{
return x>y?:x,y;
}
/*宏定义 */
#define MAX(x,y) ((x)>(y)?(x),(y))
/*写一个测试的 main()函数 */
int main(int argc,char argv)
{
printf(“use the function count is :%d/n”,max(5,2));//函数调用 A
printf(“use the macro count is:%d/n”,MAX(5,2));//宏调用 B
return 0;
}
/*注释 :当 main()函数执行到 A处时现将 A处的地址压栈 ,然后转去执行 max,发现它是一个函数 ,的要为它的变量重新再分配空间 ,完成之后再接着执行 A处之后的代码 .而当程序执行到 B处时发现是个 macro,就直接将 MAX展开 ,即将 MAX(x,y)((x)>(y)?(x),(y))代替原来的 MAX.这样既有压栈也有出栈 ,还有函数局部变量的内存开销 .由于 macro只是简单的字符替换 ,它不用额外的空间开销 .*/
2:宏的处理是只是经过简单的替换,而函数是将参数经过计算后才传递过去 ,所以在以下情况时候会出现两者的不同 .
例如还是用上面的那个例子 ,将函数 max的参数传递为 ((3+3),2),那么在调用时候先是计算出 3+3=6,然后把( 6, 2)传给 max函数 ,而当调用 MAX宏时 ,宏是不会去计算 3+3等于多少的 ,而是将宏展开然后将 (3,5)传给了它 ,结果是 5.
/*总结以下就是函数有压栈,弹栈的操作 ,费 CPU的时间 ,而一个宏是使用时候被展开 ,所以当一个宏频繁被使用的时候会占空间 */
(二 )内联函数 ,宏 ,以及函数
先解释一下什么是内联函数 ,就是一些不代循环 ,条件 ,选择等复杂结构的简单函数 ,编译器为了优化 ,将这些函数在被调用的时候像宏一样内嵌不到程序中 ,可以简单的当宏使用 ,单它还是有函数的特点 ,即参数在传递时候先计算再传递 .
(三 )const与 define的比较
const定义一个有数据类型的常量 ,例如 const int N=10;
#define定义一个等量的替换
例如如下函数 :
#include<stdio.h>
#define N 10
#define M N+1
int main(int argc,char **argv)
{
int n=10,m=n+1;
printf(“use the define the result is %d/n”,M*N);
printf(“use the m*n the result is %d/n”,m*n);
return 0;
}
输出结果 :use define is :20
use m*n=110
/*应为宏只是简单的替换 ,所以在做 M*N时 ,做替换即 :10+1*10=20,如果是 N*M则是 10*10+1=101*/
(四 )#define MACRO do{ }while(0);的好处 .
安全保证 { }中的所有语句作为一个整体 ,尤其在 if语句中例如 :
#define PRINT do{printf(“hello/n”);printf(“world/n”);}while(0)
/*在 main中这样调用 */
int main()
{
int i=10;
if(i==0) PRINT; //if不成立 ,将宏展开 ,第一句不执行 ,但第二句还是要执行的 */
return 0;
}
输出结果为 :world
也就是在 if不成立的情况下调用宏 ,而且该宏是不止一条语句 ,那么此时就得不到预期结果了 ,解决的方法是在定义宏的时候加上 do{ }while(0)