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

时间:2012-07-08 04:56:09

标签: c gcc compiler-construction

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

gcc hello.c -o hello

它仍然有用..

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

  

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

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

谢谢!

2 个答案:

答案 0 :(得分: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;
}

在Ubuntu上,当我用

编译它时
$ gcc c.c -o c

它抱怨对pow的未定义引用;添加-lm会更正它。

但是这个:

$ gcc -DCONSTANT c.c -o c

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

$ gcc -fno-builtin -DCONSTANT c.c -o c

再次抱怨对pow的未定义引用。

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

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

答案 1 :(得分:5)

GCC提供了几个标准库函数built-ins

  

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

     

其余功能仅用于优化目的。

如果您查看内置插件列表,您会看到pow就是其中之一。

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