log(10.0)可以编译,但log(0.0)不能使用未定义的引用? [英] log(10.0) can compile but log(0.0) cannot with undefined reference?

查看:384
本文介绍了log(10.0)可以编译,但log(0.0)不能使用未定义的引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于以下 C 源代码:

#include <math.h>

int main(void)
{
    double          x;

    x = log(0.0);

    return 0;
}

当我使用gcc -lm进行编译时,我得到了:

When I compile with gcc -lm, I got:

/tmp/ccxxANVH.o: In function `main':
a.c:(.text+0xd): undefined reference to `log'
collect2: error: ld returned 1 exit status

但是,如果我将log(0.0)替换为log(10.0),则它可以成功编译.

But, if I replace log(0.0) with log(10.0), then it can compile successfully.

我不太了解这一点,因为无论它们是否具有数学意义,都应该进行编译-没有语法错误.有人可以解释吗?

I don't quite understand this, since no matter they make mathematical sense or not, they should compile -- there is no syntax error. Could anyone explain this?

以防万一,我的gcc -v输出:

Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.2-19ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1)

请注意,此问题与固定折叠有关,但建议重复的问题与缺少的链接库有关.

Note that this question is about constant folding but the suggested duplicate question is about a missing linking library.

推荐答案

gcc可以使用内置函数:

其中许多功能仅在某些情况下进行了优化;如果他们 在特定情况下未优化,则调用库函数 被发射.

Many of these functions are only optimized in certain cases; if they are not optimized in a particular case, a call to the library function is emitted.

因此,gcc在使用内置函数时不需要链接到数学库,但由于log(0)

so therefore gcc will not need to link against the math library when using the builtin function but since log(0) is not defined it probably forcesgcc to evaluate it at run-time since it has a side effect.

如果我们查看 C99标准草案在第 4 段中的7.12.1 错误条件的处理部分中说(强调我的):

If we look at the draft C99 standard section 7.12.1 Treatment of error conditions in paragraph 4 it says (emphasis mine):

如果数学值的大小,则浮动结果会溢出 结果是有限的,但太大,以至于数学结果不能是 在没有异常舍入误差的情况下表示 指定的类型.如果浮动结果溢出并且默认舍入为 实际上,或者如果数学结果是从 有限参数(例如log(0.0)),则函数返回 宏HUGE_VAL,HUGE_VALF或HUGE_VALL的值取决于 返回类型,其符号与函数的正确值相同; 如果整数表达式math_errhandling& MATH_ERRNO不为零, 整数表达式errno获取值ERANGE; 表达式math_errhandling& MATH_ERREXCEPT为非零, 如果 数学结果是精确的无穷大和溢出" 否则会引发浮点异常.

A floating result overflows if the magnitude of the mathematical result is finite but so large that the mathematical result cannot be represented without extraordinary roundoff error in an object of the specified type. If a floating result overflows and default rounding is in effect, or if the mathematical result is an exact infinity from finite arguments (for example log(0.0)), then the function returns the value of the macro HUGE_VAL, HUGE_VALF, or HUGE_VALL according to the return type, with the same sign as the correct value of the function; if the integer expression math_errhandling & MATH_ERRNO is nonzero, the integer expression errno acquires the value ERANGE; if the integer expression math_errhandling & MATH_ERREXCEPT is nonzero, the ‘‘divide-by-zero’’ floating-point exception is raised if the mathematical result is an exact infinity and the ‘‘overflow’’ floating-point exception is raised otherwise.

在一个实时示例中,我们可以看到使用-S标志生成程序集,使用grep log过滤出对log的调用.

We can see from a live example using -S flag to generate assembly and grep log to filter out calls to log.

对于log(0.0),将生成以下指令( 实时查看 ):

In the case of log(0.0) the following instruction is generated (see it live):

call    log

,但在log(10.0)的情况下,不会生成call log指令,( 实时观看 ).

but in the case of log(10.0) no call log instruction is generated, (see it live).

我们通常可以通过使用gcc使用内置函数. rel ="nofollow noreferrer"> -fno-builtin标志,这可能是测试是否正在使用内置函数的更快方法.

We can usually prevent gcc from using builtin function by using the -fno-builtin flag which is probably a quicker way to test whether a builtin is being used.

请注意,-lm 需要在源文件之后进行搜索,例如(来自链接的答案),如果main.c需要数学库,则可以使用:

Note that -lm needs to go after the source file, for example (taken from linked answer) if main.c required the math library then you would use:

 gcc main.c -lm 

这篇关于log(10.0)可以编译,但log(0.0)不能使用未定义的引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆