C语言 inline内联函数与带参宏

C语言 inline内联函数与带参宏

一、简述

        简单的介绍inline内联函数、带参宏的作用。

二、函数的执行与调用

        函数执行:会将之前的栈的顶,栈基址压栈,并在栈中开辟空间存放传入的参数数据。返回时将返回数据放到通用寄存器,并释放栈空间。

        函数调用:在C语言中,程序式顺序执行的,函数调用时,转移到函数所存放的内存中的某个地址,将函数执行完之后,再返回到调用之前的位置,继续执行。这种转移再回来操作,要求在转移之前保护现场(当时的执行状态,如寄存器的值,程序执行到带那里,堆栈的使用情况等),在转回之后要先恢复现场,然后继续执行。

        函数调用会增加时间和空间的开销。频繁的调用函数会影响程序的执行效率。

        但是函数功能最好单一(一个函数一个功能),那么有时候就需要将某一些代码功能封装为函数模块,以方便多次调用,加上有意义的函数名简洁易懂,方便维护。

三、带参宏

       为了将某一部分代码功能封装,但是又不想经过函数调用,我们可以使用带参宏来实现。

      如:求最大值、最小值的函数

int Max(int x, int y) // 求两个整数的最大值
{
    return (x>y?x:y);
}

int Min(int x, int y)// 求两个整数的最小值
{
    return (x<y?x:y);
}

   如果在编程中多处需要求两个数的最值,将其封装成一个功能函数,让代码更加的简介,清晰,容易维护。

   但是这个函数的代码量很少,多处调用,封装成为函数就会花费时间和空间在函数调用上,会降低程序的执行效率。

   在这种情况下,带参宏就能很好的解决:既能实现一定的封装,又不会降低程序的执行效率。

   将其编写为带参宏:

#define MAX(x,y) (x>y?x:y)
#define MIN(x,y) (x<y?x:y)

 我们可以像函数一样调用,但它不是函数,而是宏,在预编译阶段就展开,其实就是简单的替换。

 如:

int a = 5;
int b = 8;

int c = Max(a, b);// 函数方式调用

int c = MAX(a, b);// 带参宏方式,在预编译阶段,这一句就会展开成为 int c = (a>b?a:b); 

//其实就是简单的宏替换 将 MAX(a, b) 替换成为 (a>b?a:b)

注1:C语言编从C代码译成可执行文件依次经过4个阶段:预编译、编译、汇编、链接

         预编译:处理预编译指令,如#include(文件包含),#define(宏替换),#if(条件编译)等

         编译:将C代码编译生成汇编代码

         汇编:将汇编代码生成目标文件(二进制文件)

         链接:链接其他目标文件、动态库、静态库--》生成可执行文件。

注2:宏定义一般会将参数加小括号以确保优先级(也就是无恶报按照自己的意愿顺序执行)

         如:

#define MAX(x,y) (x>y?x:y) 会写为  #define MAX(x,y) ( (x)>(y)?(x):(y) )

        举例:不加小括号会出现的问题

// 以下定义一个求积的带参宏
#define MLT(x,y) x*y      //或define MLT(x,y) (x*y)     

//宏一般使用大写 multiplication:乘法


假设有
int a = 5;
int b = 8;

int c = MLT(a,b);// 等价 int c = a*b;可以正确得出结果

如果是

int c = MLT(a+2,b);// 等价int c = a+2*b  结果为21,与预期的(a+2)*b=(5+2)*8=56不同。

 带参宏的优缺点:

优点:1) 在一定封装性的同时提高执行效率。

           2)可以简单的实现"重载"。(对同一功能不同参数类型的兼容)

缺点:1) 因为是纯文本替换,不会进行参数类型检查,并且容易出现优先级问题。

           2) 不方便调试。

           3) 如果调用的此时很多,那么执行代码会增多。

四、内联函数 (inline)

        在普通函数前面加上关键字inline,这个函数就称为内联函数。如:

inline int Max(int x, int y) // 求两个整数的最大值
{
    return (x>y?x:y);
}

     内联函数在编译时期展开,就是将 要调用的内联函数的代码 在调用的地方复制一份。这样不用经过函数调用,提高执行效率。

内联函数的优缺点:

优点:1) 不用经过函数调用,提高执行效率。

           2) 相对带参宏,在调试程序时有更多有用的调试信息。

           3) 进行参数类型检查。

缺点:1) 最终由编译器决定是否内联,而且不能有递归,否则产生无穷展开。

           2) 内联函数的使用可能大大增加编译时间。

           3) 如果多处调用,会增加代码量。

五、总结

       无论是带参宏,函数内联函数,都有着"减少函数调用,提高执行效率"的目的。并且都有着"简洁的封装"的意思。

所以想要将某一动作作为带参宏或者是内联函数,这个动作最好要"简单"一点,最好不要有多层嵌套的循环,不要有递归调用。

宏:简单的纯文本替换(在预编译阶段展开)。

内联函数:将函数代码复制到要调用的地方(在编译阶段展开)。

猜你喜欢

转载自blog.csdn.net/nanfeibuyi/article/details/84063218