C -GCC无法在没有-O2的情况下进行内联功能



我最近遇到了一个问题,即在升级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标志一起使用,但我希望它能起作用?

将" -o"选项添加到编译器命令中。仅在启用优化时才打开插入。

c99内联函数

默认情况下,clang在GNU C11模式下构建C代码,因此它使用标准的C99语义为Inline关键字。这些语义与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中,内联表示函数的定义仅用于内线,并且程序中的其他地方还有另一个定义(无内联)。这意味着此程序是不完整的,因为如果添加未插入(例如,在没有优化的情况下编译时),则MAIN将对其他定义有尚未解决的引用。因此,我们将获得这样的(正确的)链接时间错误:

Undefined symbols:
  "_add", referenced from:
      _main in cc-y1jXIr.o
相比之下,

GNU C89模式(默认情况下,在旧版本的GCC中使用)是C89标准和许多扩展。C89没有内联关键词,但GCC将其视为扩展名,只是将其视为优化器的提示。

有几种解决此问题的方法:

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

所有这些仅适用于C代码;c 中的内联含义与gnu89或c99中的含义非常不同。

相关内容

  • 没有找到相关文章

最新更新