【问题标题】:gcc - 2 versions, different treatment of inline functionsgcc - 2 个版本,内联函数的不同处理
【发布时间】:2010-06-23 09:29:14
【问题描述】:

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

main.c:

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

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

文件.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.c 和 file.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 被破坏了,我不应该在几个翻译单元中有多个内联函数定义,除非它们是静态的?

【问题讨论】:

    标签: c gcc compiler-construction inline c99


    【解决方案1】:

    是的,从 gcc-4.3 开始,该行为已更改。 gcc 内联文档 (http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Inline.html) 对此进行了详细说明。

    简短的故事:纯内联仅用于告诉 gcc(无论如何在旧版本中) 从同一文件范围内内联调用。但是,它并没有告诉 gcc 所有调用者都来自文件范围,因此 gcc 还保留可链接版本 f() around: 这解释了你上面的重复符号错误。

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

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

    现在问题来了:我应该如何定义和声明我想要内联的简单和小函数,以便它们可以在整个项目中使用而不用担心各种编译器中的问题?将它们全部设为静态是正确的做法吗?或者 gcc-4 被破坏了,我不应该在几个翻译单元中有多个内联函数定义,除非它们是静态的?

    如果您想要跨 gcc 版本的可移植性,请使用静态内联。

    【讨论】:

      猜你喜欢
      • 2020-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-19
      • 1970-01-01
      • 2020-05-19
      • 2019-10-24
      相关资源
      最近更新 更多