以下是在x86_64上运行的一些简单测试,以显示使用内联语句时生成的汇编代码:
测试1
static inline void
show_text(void)
{
printf("Hello\n");
}
int main(int argc, char *argv[])
{
show_text();
return 0;
}
和汇编程序:
gcc -O0 -fno-asynchronous-unwind-tables -S -masm=att main.c && less main.s
.file "main.c"
.text
.section .rodata
.LC0:
.string "Hello"
.text
.type show_text, @function
show_text:
pushq %rbp
movq %rsp, %rbp
leaq .LC0(%rip), %rdi
call puts@PLT
nop
popq %rbp
ret
.size show_text, .-show_text
.globl main
.type main, @function
main:
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
movl %edi, -4(%rbp)
movq %rsi, -16(%rbp)
call show_text
movl $0, %eax
leave
ret
.size main, .-main
.ident "GCC: (GNU) 7.3.1 20180312"
.section .note.GNU-stack,"",@progbits
测试1结果:编译器未考虑内联建议
测试2
代码与测试1相同,但带有-O1优化标志
gcc -O1 -fno-asynchronous-unwind-tables -S -masm=att main.c && less main.s
.file "main.c"
.text
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "Hello"
.text
.globl main
.type main, @function
main:
subq $8, %rsp
leaq .LC0(%rip), %rdi
call puts@PLT
movl $0, %eax
addq $8, %rsp
ret
.size main, .-main
.ident "GCC: (GNU) 7.3.1 20180312"
.section .note.GNU-stack,"",@progbits
测试2结果:不再在汇编器中定义show_text函数
测试3 show_text未声明为内联,-O1优化标志
测试3结果:不再有在汇编器中定义的show_text函数(带或不带inline:生成的代码相同)
测试4
#include <stdio.h>
static inline void
show_text(void)
{
printf("Hello\n");
printf("Hello\n");
printf("Hello\n");
printf("Hello\n");
printf("Hello\n");
printf("Hello\n");
}
int main(int argc, char *argv[])
{
show_text();
show_text();
return 0;
}
产生:
gcc -O1 -fno-asynchronous-unwind-tables -S -masm=att main.c && less main.s
.file "main.c"
.text
.section .rodata
.LC0:
.string "Hello"
.text
.type show_text, @function
show_text:
pushq %rbp
movq %rsp, %rbp
leaq .LC0(%rip), %rdi
call puts@PLT
leaq .LC0(%rip), %rdi
call puts@PLT
leaq .LC0(%rip), %rdi
call puts@PLT
leaq .LC0(%rip), %rdi
call puts@PLT
leaq .LC0(%rip), %rdi
call puts@PLT
leaq .LC0(%rip), %rdi
call puts@PLT
nop
popq %rbp
ret
.size show_text, .-show_text
.globl main
.type main, @function
main:
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
movl %edi, -4(%rbp)
movq %rsi, -16(%rbp)
call show_text
call show_text
movl $0, %eax
leave
ret
.size main, .-main
.ident "GCC: (GNU) 7.3.1 20180312"
.section .note.GNU-stack,"",@progbits
测试4结果: show_text
在汇编器中定义,未考虑内联建议
我了解inline关键字不会强制内联。但是对于测试1 结果,什么可以防止main中的show_text
代码替换?
到目前为止,我曾经在C源代码中内联一些小的静态函数。但是,从这些结果来看,它似乎毫无用处。
在使用某些现代编译器(并可能会编译优化的代码)时,为什么要声明我的一些小函数static inline
?
答案 0 :(得分:0)
这是C语言标准人员的可疑决定之一...使用inline
不能保证内联函数...该关键字仅向编译器建议该函数可以内联。
我已经与ISO WG进行了长时间的交流;这遵循了MISRA指南,该指南要求使用inline
关键字在模块范围内声明所有static
函数。他们的逻辑是,在某些情况下编译器不需要内联函数...同样,在某些情况下,未内联函数需要具有全局作用域!
恕我直言,如果程序员添加了inline
关键字,那么建议是他们知道自己在做什么,并且该函数应该是内联的。
正如您所建议的那样,除非编译器认真对待它,否则inline
关键字实际上是毫无意义的。
答案 1 :(得分:0)
在您的第一个测试中,您禁用了优化。内联是一种优化方法。不要期望它会发生。
inline
关键字现在也不再像过去一样有效。我要说的唯一目的是在标头中包含函数,而不会出现有关重复符号的链接器错误(当多个cpp文件使用此类标头时)。
让您的编译器执行其工作。只需启用优化(包括LTO),就不必担心细节。