Jef*_*mes 3 c optimization inline c99 clang
我正在尝试使用各种优化级别的clang编译以下代码:
#include <stdio.h>
inline int foo() { return 42; }
int main() {
printf("%d\n", foo());
}
Run Code Online (Sandbox Code Playgroud)
在-O1,-O2,-O3,和-Os,它编译成功,但使用时失败-O0:
$ clang -O0 -o main main.c
Undefined symbols for architecture x86_64:
"_foo", referenced from:
_main in main-8b9319.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Run Code Online (Sandbox Code Playgroud)
Clang的内联兼容性-O0可以解释(和变通方法)的失败,但是无论优化级别如何,我都天真地期望这会失败.似乎一些优化已经启用了一些东西来阻止这种链接错误的发生,但我很好奇它们是什么样的优化,以及为什么它们似乎具有不同于单独使用的语义.-O1inline-O0
在-O1和更大的他并没有叫这只是移动代码到功能main,我们可以通过查看此godbolt这说明ASM如下现场观看:
main: # @main
pushq %rax
movl $.L.str, %edi
movl $42, %esi
xorl %eax, %eax
callq printf
xorl %eax, %eax
popq %rdx
retq
Run Code Online (Sandbox Code Playgroud)
这是什么引用说:
[...]因为如果没有内联添加(例如,在没有优化的情况下进行编译),那么main将会有一个未解析的对其他定义的引用[...]
草案C99标准部分6.7.4 功能说明符包括:
具有内部链接的任何函数都可以是内联函数.对于具有外部链接的函数,以下限制适用:如果使用内联函数说明符声明函数,则它也应在同一转换单元中定义.如果转换单元中函数的所有文件范围声明都包含不带extern的内联函数说明符,则该转换单元中的定义是内联定义.内联定义不提供函数的外部定义,也不禁止另一个转换单元中的外部定义.内联定义提供了外部定义的替代,翻译器可以使用该定义在同一翻译单元中实现对该功能的任何调用.未指定对函数的调用是使用内联定义还是使用外部定义.222)
这个网站有很好的语言解释:C99中棘手的内联说明符