考虑以下具有
inline
函数的C++代码:// this function is in a header-file:
// recursion prevents inlining
inline int calc(int k){
if(k<=1) return 1;
return calc(k-1)+calc(k-2);
}
// this function is in a source-file:
int fun(int k){
return calc(k);
}
我在这里使用递归来模拟编译器无法内联函数calc
的情况。
生成的汇编代码(使用-Os
编译,查看https://godbolt.org/上的实时演示):
...
.weak calc(int)
.type calc(int), @function
calc(int):
// some assembler
.text
.globl fun(int)
.type fun(int), @function
fun(int):
...
jmp calc(int)
正如预期的那样,编译器无法内联calc
函数,因此会为其发出代码,但由于使用了inline
关键字,它成为一个弱符号。
将相同的代码编译为C语言,会产生不同的结果(使用-Os
选项,可以在https://godbolt.org/上实时查看):
.Ltext0:
.globl fun
.type fun, @function
fun:
...
jmp calc
最显著的区别是:对于calc
没有任何代码生成,所以基本上链接器无法将可执行文件链接起来,因为缺少calc
的定义。
显然,inline
在C和C++中有不同的含义。
C和C++中inline
的区别是什么?如何定义calc
,使其可以同时在C和C++的头文件中使用?
__attribute((always_inline))
,它会给您一个错误:error: inlining failed in call to 'always_inline' 'int calc(int)': recursive inlining
。或者指定extern
,它将执行C++中的操作。请参见https://en.cppreference.com/w/c/language/inline中的“注意”部分以了解差异。 - Brandoninline
行为和-Os
标志看起来有点奇怪 - 内联通常会导致更大的代码大小,而-Os
是一个最小化代码大小的标志。因此,它看起来是一种不同的启发式方法,使用-O2
进行检查更自然。 - dewaffled