返回一个封装的内联函数

时间:2018-08-25 08:14:37

标签: c linux driver inline

我正在清理用C编写的驱动程序(Netgear A6210)中的一些代码,并且遇到了一个辅助函数VIRTUAL_IF_DOWN(),该函数被强制内联(例如,__inline而不是inline),并在末尾包含看似任意的return语句。

__inline void VIRTUAL_IF_DOWN(void *pAd)
{
    /* Some code here */
    return ;
}

但是,在将控制权交还给程序的其余部分之前,在其他两个函数的主体中调用了此辅助函数,所以我的问题是,此return语句是否与该函数的其余部分内联,从而破坏了退出更大的功能还是什么都不做?我对内联函数的一般经验法则是,我应该始终将它们视为单独的函数,而不是假定它们将按原样内联,无论如何,我以其中的一个封装函数为例:

static void rtusb_disconnect(struct usb_interface *intf)
{
    /* Some code here and then an ugly looking preprocessor branch */       
#ifdef IFUP_IN_PROBE
    VIRTUAL_IF_DOWN(pAd); // Function is used here
#endif
    /* Other code here */
}

我为混乱的样板代码表示歉意,但是即使return语句刚刚被内联,它似乎也使代码变得混乱。隐藏可能影响内联函数背后的流程的语句似乎是一种不好的做法。有什么更好的解决方案?

我的问题的另一部分是,内联是在编译的预处理阶段还是之后的阶段确定的,例如在汇编器或链接器阶段?

2 个答案:

答案 0 :(得分:2)

与宏预处理相比,内联不仅仅是复制粘贴代码。

当编译器遇到任何类型的内联指令时,它会评估内联函数返回或执行的操作。

您可以使用godbolt.org之类的网站来查看为C代码生成的程序集。例如,以下函数求值为相同的汇编代码:

#include <stdio.h>

inline void test1(int number){
    printf("%d", number);
    return;
}

inline int test2(){
    return 1+1;
}

void doSomething() {
    test1(test2());
}

void doSomethingElse() {
    printf("%d", 2);
}

和程序集:

.LC0:
        .string "%d"
_Z11doSomethingv:
        sub     rsp, 8
        mov     esi, 2
        mov     edi, OFFSET FLAT:.LC0
        mov     eax, 0
        call    printf
        add     rsp, 8
        ret
_Z15doSomethingElsev:
        sub     rsp, 8
        mov     esi, 2
        mov     edi, OFFSET FLAT:.LC0
        mov     eax, 0
        call    printf
        add     rsp, 8
        ret

您可以在https://godbolt.org/z/rBULdo

看到此示例

您还应该注意,内联是编译器优化。不同的编译标志可能导致内联的结果不同。

这还取决于编译时相对于运行时可用的信息量。如果编译器在编译时了解更多信息,那么它可以进行更好的优化,然后如果仅在运行时才知道所有内容,那该怎么办?

在遇到inline属性时,请参阅link,以了解GCC的行为

答案 1 :(得分:1)

return;函数末尾的

void是多余的。

内联保留语义:如果return从非内联调用返回,则内联函数中的return从内联“调用”返回,即,它跳转到内联主体的末尾。

内联发生在编译期间,即在预处理和解析之后,但在代码生成和组装之前。