我正在读一本关于海湾合作委员会的书。它表示,对于任何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>
谢谢!
答案 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
添加到编译器选项中,则应该得到您期望的链接器错误。