【问题标题】:gcc fails to inline functions without -O2gcc 无法在没有 -O2 的情况下内联函数
【发布时间】:2016-12-19 19:10:12
【问题描述】:

我最近在升级 debian 测试并获得 gcc 6.2.1 编译器后编译一段代码时遇到了问题。我把它归结为这个简单的例子:

inline int func(void) {
    return 0;
}

int main (int argc, char **argv) {
    func();
}

代码确实编译如下:

gcc -o exec code.c # gcc 6.2.1

它失败了:

undefined reference to 'func'

我也在同一台主机上尝试过使用 gcc 4.8、4.9 和 5,但都失败了。 如果我添加它会编译:

gcc -o exec code.c -O2 # gcc 6.2.1

我真的很好奇为什么它与 -O2 标志一起工作,但不是没有,我希望这能工作?

【问题讨论】:

  • 你是什么意思“[t]他的代码编译”?你得到什么错误?请编辑您的问题以包含编译器的完整、完整和未经编辑的输出。
  • 我们必须重复多少次 inline 所做的事情......说真的......
  • 您的程序无法编译,因为func 中没有return 语句。功能。编译器的错误信息非常清楚。
  • 我猜这个问题已经在其他问题中得到了回答,所以如果您愿意,可以将其删除,但是,Sumit 下面的回答比我见过的大多数其他回答都要好。跨度>

标签: c gcc optimization inline gcc6


【解决方案1】:

在编译器命令中添加“-O”选项。仅当启用优化时才启用内联。

C99 内联函数

默认情况下,Clang 在 GNU C11 模式下构建 C 代码,因此它对 inline 关键字使用标准 C99 语义。这些语义不同于 GNU C89 模式中的语义,后者是 5.0 之前的 GCC 版本中的默认模式。例如,考虑以下代码:

inline int add(int i, int j) { return i + j; }

int main() {
  int i = add(4, 5);
  return i;
}

在 C99 中,内联意味着一个函数的定义仅用于内联,并且在程序的其他地方还有另一个定义(没有内联)。这意味着这个程序是不完整的,因为如果 add 没有内联(例如,在没有优化的情况下编译时),那么 main 将有一个未解析的对另一个定义的引用。因此我们会得到一个(正确的)链接时错误,如下所示:

Undefined symbols:
  "_add", referenced from:
      _main in cc-y1jXIr.o

相比之下,GNU C89 模式(在旧版本的 GCC 中默认使用)是 C89 标准加上许多扩展。 C89 没有 inline 关键字,但 GCC 将其识别为扩展,并将其视为对优化器的提示。

有几种方法可以解决这个问题:

  1. 更改添加到静态内联函数。如果只有一个翻译单元需要使用该功能,这通常是正确的解决方案。静态内联函数始终在翻译单元中解析,因此您不必在程序的其他位置添加函数的非内联定义。
  2. 从 add 的定义中删除 inline 关键字。内联函数不需要 inline 关键字,也不保证一定会这样。一些编译器完全忽略它。 Clang 将其视为程序员的温和建议。
  3. 在程序中的其他位置提供外部(非内联)添加定义。这两个定义必须相等!
  4. 通过将 -std=gnu89 添加到 Clang 选项集以 GNU C89 方言编译。仅当程序源无法更改或程序还依赖其他无法更改的 C89 特定行为时,才建议使用此选项。

所有这些仅适用于 C 代码; C++ 中 inline 的含义与 GNU89 或 C99 中的含义大不相同。

【讨论】:

  • OP 使用 gcc 编译,而不是 clang。
  • 感谢您的解释 :)。我没有注意到 inline 在 c99 及更高版本中不能独立使用。如果不添加会与“内联添加”功能发生冲突的“添加”功能,您将如何提供外部非内联?
猜你喜欢
  • 2020-11-11
  • 2012-05-05
  • 2015-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-29
  • 2021-03-22
相关资源
最近更新 更多