inline关键字仅仅是建议编译器做内联展开处理,而不是强制。在gcc编译器中,如果编译优化设置为O0,即使是inline函数也不会被内联展开,除非设置了强制内联(__attribute__((always_inline)))属性。对于可展开与必须当成函数的情形同时出现,则在展开处需展开,在当成函数调用处则当函数处理.
有下面几个文件
test.h ,test6.c,test7.c
test.h
inline int fun(int i){ return i+1; }test6.c
#include "test.h" int main(){ int i=0; // for(;i>-1;) i = fun(89); return 0; }test7.c
inline int fun(int i){ i = 15; return i+1; }
gcc的static inline相对于static函数来说只是在调用时建议编译器进行内联展开;gcc不会特意为static inline函数生成独立的汇编码,除非出现了必须生成不可的情况(例如函数指针调用和递归调用);
I)不展开
函数本身递归等;函数的地址被使用时(赋予函数指针)
II)展开
gcc会在其调用处将其汇编码展开编译而不为这个函数生成独立的汇编码.
测试:
在a.h中函数名前加static
static inline int fun(int i) ;
$ gcc test6.c -S -o a.o
$ vi a.o
.file "test6.c" .text .globl fun .type fun, @function fun: pushl %ebp movl %esp, %ebp movl 8(%ebp), %eax addl $1, %eax popl %ebp ret .size fun, .-fun .globl main .type main, @function main: pushl %ebp movl %esp, %ebp subl $20, %esp movl $0, -4(%ebp) movl $89, (%esp) call fun movl %eax, -4(%ebp) movl $0, %eax leave ret .size main, .-main .ident "GCC: (GNU) 4.4.6 20120305 (Red Hat 4.4.6-4)" .section .note.GNU-stack,"",@progbits
gcc的inline函数相对于普通的extern函数来说只是在同一个文件内调用时建议编译器进行内联展开;gcc一定回为inline函数生成一份独立的汇编码以供外部文件调用。在其它文件看来,这个inline函数和普通的extern函数无异;gcc的inline函数是全局性的:在文件内可以作为一个内联函数被内联展开,而在文件外可以调用它。
gcc的static inline和inline比较容易理解,可以认为是对普通函数添加可内联的属性。
测试:
发现编译出来的汇编代码与上面的一样
测试 :
将test.h改成:
extern inline int fun(int i){ return i+1; }
$vi test6.s
.file "test6.c" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp andl $-16, %esp subl $32, %esp movl $0, 28(%esp) movl $89, (%esp) call fun movl %eax, 28(%esp) movl $0, %eax leave ret .size main, .-main .ident "GCC: (GNU) 4.4.6 20120305 (Red Hat 4.4.6-4)" .section .note.GNU-stack,"",@progbits
gcc绝不会为extern inline的函数生成独立的汇编码;extern inline函数允许和全局函数重名,可以在文件范围内替代外部定义的全局函数;使用extern inline时必须给予文档注释!!!!
将a.h改成:
inline __attribute((always_inline)) int fun(int i){ return i+1; }
.file "test6.c" .text .globl fun .type fun, @function fun: pushl %ebp movl %esp, %ebp movl 8(%ebp), %eax addl $1, %eax popl %ebp ret .size fun, .-fun .globl main .type main, @function main: pushl %ebp movl %esp, %ebp subl $16, %esp movl $0, -8(%ebp) movl $89, -4(%ebp) movl -4(%ebp), %eax addl $1, %eax movl %eax, -8(%ebp) movl $0, %eax leave ret .size main, .-main .ident "GCC: (GNU) 4.4.6 20120305 (Red Hat 4.4.6-4)" .section .note.GNU-stack,"",@progbits
参考:http://www.cnblogs.com/openix/archive/2012/11/18/2775625.html
http://blog.csdn.net/baozi3026/article/details/5372268