宏与函数

来源:互联网 发布:梦幻之星nova捏脸数据 编辑:程序博客网 时间:2024/05/16 06:05

1.宏与函数

在定义方式上两者有所不同,宏定义方式为:#define MAX(a,b) ((a)>(b)?(a):(b))

函数定义:int max(int a,int b){return a>b?a:b;}
宏的名称常为大写,用于与普通函数区分。

在一行写不下时,可以用反斜杠隔开,

# define MAX(a,b) \

((a)>(b)?(a):(b))

若想取消宏定义,可以用#undef …

# define N 5

#undef N

宏的优点是它在预处理的地方展开,不需要额外的时间开销,省去了堆栈分配,压栈出栈,释放堆栈等操作,所以调用宏比调用一个函数更有效率。另外,宏与类型是无关的。函数的参数必须声明为一种特定的类型,所以它只能在类型合适的表达式上使用。举例来说#define MAX(a,b) ((a)>(b)?(a):(b))

这里,a,b可以为char,int,usigned intdouble等类型,如果用函数,必须限定为某种类型,这里也是宏的优势所在。

# define MAL(type) \

((type *)malloc(sizeof(type)))
上面的例子可以实用MAL(int) MAL(char)等形式,而这个功能用函数是无法实现的,因为函数无法将类型关键字传入函数体。

宏也有不尽如人意的地方,比如  #define f(x)  (x*x) ,如果是求f(5)会得到25,而求f(2+3)时,并不会得到25,而是2+3*2+3=11。在定义宏的时候需要注意的是括号,每个变量或者表达式尽量加上括号,以避免产生歧义。

在宏参数在宏定义中出现的次数不止一次,如果这个参数具有副作用,那么当你使用这个宏的时候可能会出现危险,导致不可预测的结果。考虑一下代码,

# define MAX(a,b) ((a)>(b)?(a):(b))

x=5;

y=8;

z=MAX(x++,y++);

printf(“x=%d,y=%d,z=%d\n”,x,y,z);

这段代码的执行结果是  x=6,y=10,z=9.

要理解这个结果,只要展开宏的代码即可,

z=((x++)>(y++))?(x++):(y++)

较小的值增加了一次,而较大的值增加了两次!

 

宏与函数的区别

属性

# define

函数

代码长度

宏代码插入到程序中,除了非常小的宏之外,程序的长度将大幅度增长

函数代码只出现在一个地方

执行速度

更快

存在额外开销

操作符优先级

要为参数加上括号

 

参数求值

参数求值可能有副作用

参数多次求值没有副作用

参数类型

与类型无关

与类型有关

 一个小例子:

不使用比较操作符,利用宏来比较两个整型数的大小

# define MAX(a,b)  (((a)-(b))>>31)?(b):(a)

上面的例子中假定了int 型数据变量占据4个字节,a-b右移31位即可得到符号位,符号位为1时a<b,符号位为0时,a>b.

 

2内联函数与宏的区别

内联函数和宏的区别在于,宏是由预处理器对宏进行替代,而内联函数是通过编译器控制来实现的。而且内联函数是真正的函数,只是在需要用到的时候,内联函数像宏一样的展开,所以取消了函数的参数压栈,减少了调用的开销。你可以象调用函数一样来调用内联函数,而不必担心会产生于处理宏的一些问题。

我们可以用Inline来定义内联函数,不过,任何在类的说明部分定义的函数都会被自动的认为是内联函数。内联函数也有一定的局限性。就是函数中的执行代码不能太多了,如果,内联函数的函数体过大,一般的编译器会放弃内联方式,而采用普通的方式调用函数。这样,内联函数就和普通函数执行效率一样了,内联函数中一般没有循环和递归等结构。

0 0
原创粉丝点击