gcc - 2个版本,内联函数的不同处理

时间:2010-06-23 09:29:15

标签: c gcc compiler-construction inline c99

最近我在我的项目中遇到了一个问题。我通常在gcc-4中编译它,但在尝试在gcc-3中编译之后,我注意到了对内联函数的不同处理。为了说明这一点,我创建了一个简单的例子:

main.c中:

#include "header.h"
#include <stdio.h>

int main()
{
    printf("f() %i\n", f());
    return 0;
}

file.c:

#include "header.h"
int some_function()
{
    return f();
}

header.h

inline int f()
{
    return 2;
}

当我使用:

编译gcc-3.4.6中的代码时
gcc main.c file.c -std=c99 -O2

我得到链接器错误(f的多个定义),如果删除-O2标志,则相同。我知道编译器不必内联任何内容,如果它不想,所以我假设它在对象文件中放置f而不是在main.cfile.c的情况下内联它,因此多个定义错误。显然我可以通过使f静态来解决这个问题,然后,在最坏的情况下,在二进制文件中有一些f

但是我尝试用gcc-4.3.5编译这段代码:

gcc main.c file.c -std=c99 -O2

一切正常,所以在两种情况下都假设新的gcc内联f并且二进制文件中根本没有函数f(在gdb中检查,我是对的)。

但是,当我删除-O2标志时,我得到两个未定义的int f()引用。 在这里,我真的不明白发生了什么。似乎gcc假设f将被内联,因此它没有将它添加到目标文件中,但后来(因为没有-O2)它决定生成对这些函数的调用而不是内联这就是链接器错误的来源。

现在问题是:我应该如何定义和声明我想要内联的简单和小函数,以便它们可以在整个项目中使用而不必担心各种编译器中的问题?并且让所有这些都成为静态的正确的事情吗?或者也许gcc-4被打破了,除非它们是静态的,否则我不应该在几个翻译单元中有多个内联函数的定义?

1 个答案:

答案 0 :(得分:5)

是的,行为已经从gcc-4.3开始改变了。 gcc内联文档(http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Inline.html)详细说明了这一点。

简短的故事:简单内联只能告诉gcc(无论如何都是旧版本) 内联调用来自同一文件范围。但是,它并没有告诉gcc  所有调用者都来自文件范围,因此gcc也保持可链接的版本 f()左右:这解释了上面的重复符号错误。

Gcc 4.3将此行为更改为与c99兼容。

并且,回答你的具体问题:

  

现在问题是:我应该如何定义和声明我想要内联的简单和小函数,以便它们可以在整个项目中使用而不必担心各种编译器中的问题?并且让所有这些都成为静态的正确的事情吗?或者也许gcc-4被打破了,除非它们是静态的,否则我不应该在几个翻译单元中有多个内联函数的定义?

如果您希望跨gcc版本的可移植性使用静态内联。