我正在清理用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
语句刚刚被内联,它似乎也使代码变得混乱。隐藏可能影响内联函数背后的流程的语句似乎是一种不好的做法。有什么更好的解决方案?
我的问题的另一部分是,内联是在编译的预处理阶段还是之后的阶段确定的,例如在汇编器或链接器阶段?
答案 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
从内联“调用”返回,即,它跳转到内联主体的末尾。
内联发生在编译期间,即在预处理和解析之后,但在代码生成和组装之前。