3

我正在读一本关于 GCC 的书。它说默认情况下,任何 C 程序都只链接标准库。由于pow()不在标准库中,我将不得不使用-lm标志链接到它。但是,当我编译时,我只是使用了:

gcc hello.c -o hello

它仍然有效..

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

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

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

谢谢!

4

2 回答 2

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.

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

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

于 2012-07-08T06:11:52.873 回答
5

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

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

其余函数用于优化目的。

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

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

于 2012-07-08T04:59:19.747 回答