我在我的C程序中使用了pow()函数,但没有链接到-lm它仍然有效.为什么?

Zes*_*ang 3 c compiler-construction gcc

我正在读一本关于海湾合作委员会的书.它表示,对于任何C程序,默认情况下只链接标准库.由于pow()不在标准库中,我将不得不使用-lm标志链接到它.但是,当我编译时,我只是使用:

gcc hello.c -o hello
Run Code Online (Sandbox Code Playgroud)

它仍然有效..

还有另外一个类似的问题,本书还说如果你有printf("%f\n", 4);你的C程序,如果你编译WITHOUT -Wall选项,将不会发出警告.但是,我尝试在没有-Wall选项的情况下编译它,但我仍然收到警告:

hello.c:6:2:警告:格式'%f'需要类型为'double'的参数,但参数2的类型为'int'[-Wformat]

为什么是这样?这本书说我必须提供-lm-Wall为了使我的程序编译并得到警告,但我没有使用它们中的任何一个,但我仍然编译我的程序并得到警告?

谢谢!

Kei*_*son 7

基于一些实验的更多信息.

考虑这个程序:

#include <stdio.h>
#include <math.h>
int main(void) {
#ifdef CONSTANT
    double x = pow(2.0, 10.0);
#else
    double expon = 10.0;
    double x = pow(2.0, expon);
#endif
    printf("x = %f\n", x);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在Ubuntu上,当我用它编译它时

$ gcc c.c -o c
Run Code Online (Sandbox Code Playgroud)

它抱怨未定义的引用pow; 添加-lm纠正它.

但是这个:

$ gcc -DCONSTANT c.c -o c
Run Code Online (Sandbox Code Playgroud)

编译和链接没有错误,用pow()常量替换调用1024.0.但是这个:

$ gcc -fno-builtin -DCONSTANT c.c -o c
Run Code Online (Sandbox Code Playgroud)

再次抱怨未定义的引用pow.

结论:pow只有在编译时才能确定结果时,gcc才使用内置实现.否则它会生成对pow()函数的显式调用,这需要链接-lm.

另请注意,这取决于C库的组织方式(库是单独提供的;它不是gcc的一部分).在Cygwin上,使用newlib而不是Ubuntu上使用的glibc,-lm不需要选项; 显然,数学例程是标准库的组成部分,而不是单独提供.(Cygwin上的gcc仍然接受该-lm选项.)


mu *_*ort 5

GCC提供了几个标准库函数作为内置函数:

GCC提供了除上述功能之外的大量内置功能.其中一些内容用于处理异常或可变长度参数列表,因此它们可能会不时更改,因此不会在此处记录; 我们不建议一般使用这些功能.

其余功能用于优化目的.

如果你看一下内置插件列表,你会发现它pow就是其中之一.

如果添加-fno-builtin到编译器选项,则应该得到您期望的链接器错误.