gcc 编译器对 inline 函数的支持

来源:互联网 发布:65是什么意思网络用语 编辑:程序博客网 时间:2024/05/15 21:26

C99版的C语言引入了inline关键字开始支持inline 函数,在这之前传统的C语言(C89)是没有inline 关键字的,也不支持inline 函数。不过大多数 C89 的编译器都将inline作为一种附加特性早早的就加进去了。gcc 也不例外,不过gcc增加inline特性时C99还没定型,gccinline 的语意与C99也有些许的区别。这里就主要说说gcc 中的inline 特性。

 

另外,本文只讨论C语言,C++标准中很早就支持inline,不过inline的语意CC++ 是有细微差别的。

先举一个最简单的例子

//main.c#include <stdio.h>int foo(void);int main(){    int a = foo();    printf("a = %d", a);    return 0;}//foo.cinline int inline_func(int a){    return a + 1;}int foo(void){    int x = 5;    x = inline_func(x);    return x;}

这个是inline 最简单的用法,无论是gcc 还是其他支持inline 的编译器都能编译通过。

 inline_func()是个函数(inline的),既然是函数,那么就应该允许加入函数声明。我们对 foo.c 进行些小的修改,看看结果。

//foo.cinline int inline_func(int a);inline int inline_func(int a){    return a + 1;}int foo(void){    int x = 5;    x = inline_func(x);    return x;}

编译通过,但是这样的代码实际上是不符合c99标准的。c99标准中inline 关键字只能修饰函数定义,不能修饰函数声明。用gcc编译时如加入了 -std=c99 的选项(要求gcc严格遵守c99标准),就不能编译通过。报的错误如下:

In function `foo'

undefined reference to `inline_func

 

如果在声明时去掉inline,变成如下的代码:

int inline_func(int a);inline int inline_func(int a){    return a + 1;}int foo(void){    int x = 5;    x = inline_func(x);    return x;}

则完全没有问题,无论开启与否c99,都能编译通过。

更多的时候,我们一个inline函数要在多处使用,这时如果像普通函数那样在其他文件中也声明一下,比如下面在main.c 中添加了函数声明和调用。


int inline_func(int a);int foo(void);int main(){    int a = foo();    a = inline_func(a);    printf("a = %d", a);    return 0;}

这样编译也能通过,但是通过查看汇编代码就会发现。只有foo()函数中对inline_func() 的调用被内联了,main()中还是传统的函数调用方式。说明这样用并没有达到我们期望的效果。正确的方式应该是将inline 函数放到头文件中定义。这样每个用到它的地方才会真正的内联。


#include <stdio.h>#include "inline_func.h"int foo(void);int main(){    int a = foo();    a = inline_func(a);    printf("a = %d", a);    return 0;}foo.c#include "inline_func.h"int foo(void){    int x = 5;    x = inline_func(x);    return x;}inline_func.h#ifndef INLINE_FUNC_H_INCLUDED#define INLINE_FUNC_H_INCLUDEDinline int inline_func(int a){    return a + 1;}#endif // INLINE_FUNC_H_INCLUDED

这个代码在最后链接时会报错说多次定义了inline_func()。查看汇编代码就会发现,在编译main.c 和 foo.c 时都生成了 inline_func 的代码,虽然main() 和 foo 都内联了inline_func(),所以inline_func()实际上是没用到的。但是有两份 inline_func()的代码还是会造成链接是的冲突。所以上面的代码还需要修改。一种简单的办法是将inline_func() 改为static 函数,也就是让它的作用域只在编译单元内。

 inline_func.h#ifndef INLINE_FUNC_H_INCLUDED#define INLINE_FUNC_H_INCLUDEDstatic inline int inline_func(int a){    return a + 1;}#endif // INLINE_FUNC_H_INCLUDED

这样修改之后就完全没问题了。其实到这里就可以了,不过有些人就喜欢在头文件中添加函数的声明,即使是inline函数也不例外。

 inline_func.h#ifndef INLINE_FUNC_H_INCLUDED#define INLINE_FUNC_H_INCLUDEDint inline_func(int a);static inline int inline_func(int a){    return a + 1;}#endif // INLINE_FUNC_H_INCLUDED

这样再编译又报错了。

error: static declaration of 'inline_func' follows non-static declaration

 

继续修改,改成这个样子就没问题了。

 inline_func.h#ifndef INLINE_FUNC_H_INCLUDED#define INLINE_FUNC_H_INCLUDEDstatic int inline_func(int a);static inline int inline_func(int a){    return a + 1;}#endif // INLINE_FUNC_H_INCLUDED

OK,就说这么多。inline 函数知道这么多基本就够用了。



1 1