在不链接 c 标准库的情况下使用编译器内置函数

Using compiler builtins without linking the c standard library

我看过 this question,其答案的结论是内置数学函数(如 __builtin_sin__builtin_fmod 等)可以替代 C 标准库中的函数。

我写了下面的程序:

float fmod_test(float arg1, float arg2) {
    return __builtin_fmod(arg1, arg2)
}

void _start() {}

并编译如下:

gcc -nostdlib test.c -o test

不幸的是,我收到以下错误:

/tmp/ccuHpvCP.o: In function `fmod_test':
test.c:(.text+0x1d): undefined reference to `fmod'
collect2: error: ld returned 1 exit status

似乎 __builtin_fmod 在后台使用 fmod 并且需要 link 它,而不是像 "built in" 那样生成内联版本功能。

有没有什么方法可以在不 link 访问外部库的情况下使用这些内置函数?

这个问题的答案完全取决于您使用的是哪种 C 编译器。您似乎在使用 GCC;该编译器的答案是否定的。

这些函数是 "built in",因为 GCC 知道它们的名字并且可以优化掉对它们的 一些 调用,例如 fmod(7.0, 2.0) 很可能是在编译时评估。但是 GCC 不提供这些函数的运行时定义。它依赖于 C 库,这是一个单独的项目,来提供它们。

正如the gcc manual所说:

Many of these functions are only optimized in certain cases; if they are not optimized in a particular case, a call to the library function is emitted.

因此无法保证避免调用库函数的可能性。

但是,您可以尝试调用函数的方式和优化选项,希望找到可以内联的组合。特别是,对于浮点内置函数,gcc 通常只会在 -ffast-math 有效时内联它们,因为它的内联代码可能无法达到那么高的精度或处理所有极端情况(NaN、无穷大、非正规数、设置 errno, 等等) 就像精心编写的库函数一样。此处就是这种情况,实际上,如果您启用 -ffast-math,您会得到内联代码:see on godbolt。 (打开优化会更好看。)

当然,如果您稍后更改编译器选项,或以不同的方式调用函数,或切换到不同的编译器版本,编译器可能会再次发出库调用。你会知道是否会发生这种情况,因为你的程序不会 link,所以至少它不会悄无声息地中断,然后你可以尝试重新调整你的代码 and/or 编译选项,或者如果需要,编写或导入您自己的函数版本。