在不链接 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 编译选项,或者如果需要,编写或导入您自己的函数版本。
我看过 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 编译选项,或者如果需要,编写或导入您自己的函数版本。