C语言

宏定义函数与内联函数

2020-03-22  本文已影响0人  风情云

宏定义函数

在c程序中,可以使用宏定义函数代替简单的函数,这样提高程序效率,预处理器用复制宏代码的方式代替函数调用,省去了参数压栈、生成汇编语言的CALL调用、 返回参数、执行return等过程,从而提高了速度。 缺点是使用宏代码最大的缺点是容易出错,预处理器在复制宏代码时常常产生意想不到的边际效应。

//宏定义函数
#define TEST(a) a*3
int main()
{
    int a = 2;
    int tmp = TEST(a+2);
    printf("tmp = %d\n",tmp);
}

结果

tmp = 8

结果不应该是12吗,这是因为宏定义函数不会处理表达式将a+2的值求出在传值,而是直接宏定义展开,TEST(a+2) =》 a+2*3 不做任何处理,所以结果为8,要解决这个问题就要加在宏定义时括号

#define TEST(a) (a)*3

代码展开变为 (a+2)*3 结果就正确。所以宏定义参数记得加括号。

#define MAX(a,b) (a)>(b)?(a):(b)
int main()
{
    int a = 2;
    int b = 3;
    int max = ++MAX(a,b);
    printf("max = %d\n",max);
}

结果

max = 3

结果又错了,首先展开宏定义看看,
++MAX(a,b) => ++(a)>(b)?(a):(b) 此时() 优先级大,先算括号内的,接着到++,所以a的值为3,结果就为3。解决办法:尝试返回的结果再加一层括号

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

(在c语言中)编译错误,三目运算符的返回值不能作为左值。所以一般宏定义函数不会这样用,宏定义函数返回一个常数,常数不可以作为左值。

#define MAX(a,b) (a)>(b)?(a):(b)
int main()
{
    int a = 2;
    int b = 3;
    int max = MAX(a,++b);
    printf("max = %d\n",max);
}

结果

max = 5

结果为5,为什么?宏定义展开看看:
MAX(a,++b) => (a)>(++b)?(a):(++b) 结果可以明白了,b自增两次,宏定义函数是不会处理传入的值,只会宏定义展开,所以b并没有自增为4再展开。这个有解决方法吗?这个没有。

小结

在使用宏定义函数时,尽量将参数使用括号括起来,这样会先计算参数的表达式,再运行宏定义函数内容,还有尽量不要使用自增自减运算符,结果可能不可预测。宏定义函数返回常数,不可作为左值。

内联函数

在计算机科学中,内联函数(有时称作在线函数或编译时期展开函数)是一种编程语言结构,用来建议编译器对一些特殊函数进行内联扩展(有时称作在线扩展)。这个也和宏定义函数有一样的优点,没有压栈,弹栈的开销,效率会较高。

//定义内联函数
inline void test()
{
    printf("test\n");
}

定义内联函数只需在函数定义前加“inline”关键字,注意在声明函数的加关键字并不没有定义成内联函数,要在定义时加上才可以。内联函数是在运行时直接展开函数体,所以在一些场景最好不要使用内联函数:
1.存在循环体
2.函数体比较大
3.递归函数
总之就是函数体内部需要开辟大量内存的函数不适宜定义为内联函数,会消耗大量内存,耗费时间也长。

两者不同

宏定义函数的展开是在预编译阶段,内联函数是在编译阶段。宏定义函数不会检查语法错误,而内联函数会。宏定义与参数数据类型无关,而内联函数有关。


微信号
上一篇下一篇

猜你喜欢

热点阅读