【问题标题】:I used pow() function in my C program but did not link to -lm it still worked. Why?我在我的 C 程序中使用了 pow() 函数,但没有链接到 -lm 它仍然有效。为什么?
【发布时间】:2012-07-08 04:56:09
【问题描述】:

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

gcc hello.c -o hello

它仍然有效..

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

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

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

谢谢!

【问题讨论】:

    标签: c gcc compiler-construction


    【解决方案1】:

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

    考虑这个程序:

    #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 选项。)

    【讨论】:

      【解决方案2】:

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

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

      其余函数用于优化目的。

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

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

      【讨论】:

      • 非常感谢您的回复。我也安装了 gmp 包。该文档还说我需要链接到 -lgmp 以使其可用。但是,在添加 -fno-builtin 后,我在 pow() 函数上出现错误,但在使用 gmp (mpz_t) 中定义的类型时仍然没有收到任何错误或警告。你也可以给我解释一下吗?谢谢。
      • @ZesenHuang:你在使用gmp的任何功能吗?链接器不关心类型。
      • 谢谢你是绝对正确的。但这真的很麻烦。这本书说你需要这个选项,否则它不会工作,但 GCC 本身会为你做。这里有原因吗?或者我应该问,当我将来使用 pow() 时,是否需要提供 -lm 选项? GCC 已经为我做了,但我最好自己提供吗?
      • @ZesenHuang 是的,你最好自己提供。
      • 谢谢,请问为什么?
      猜你喜欢
      • 1970-01-01
      • 2014-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-01
      • 2013-02-09
      相关资源
      最近更新 更多