日志(10.0)可以编译,但日志(0.0)不能? [英] log(10.0) can compile but log(0.0) cannot?
问题描述
有关以下的 C 的源$ C $ C:
的#include<&math.h中GT;INT主要(无效)
{
双X; X =日志(0.0); 返回0;
}
当我编译 gcc的-lm
,我得到了:
/tmp/ccxxANVH.o:在函数'主':
。交流转换器:(文字+ 0xd中):未定义引用'登录'
collect2:错误:LD返回1退出状态
但是,如果我取代日志(0.0)
与日志(10.0)
,那么它可以成功编译。
我不明白这一点,因为不管他们做数学意义与否,他们应该编译 - 没有语法错误。谁能解释一下吗?
以防万一,我的的gcc -v
输出:
配置有:../src/configure -v --with-pkgversion ='Ubuntu的4.8.2-19ubuntu1'--with-bugurl =文件:/// USR /股票/ DOC / GCC-4.8 / README.Bugs --enable-语言= C,C ++,JAVA,走,D,FORTRAN,objc,OBJ-C ++ - preFIX =的/ usr --program后缀= - 4.8 --enable-共享--enable连接体集结号--libexecdir = / usr / lib目录--without-包括-gettext的--enable-线程= POSIX --with-GXX-包括-DIR =的/ usr /包括/ C ++ / 4.8 = --libdir / usr / lib目录--enable-NLS --with-SYSROOT = / --enable-clocale = GNU --enable-libstdcxx调试--enable-libstdcxx时间= YES - 使GNU的唯一对象--disable-libmudflap --enable-插件--with-系统的zlib --disable-浏览器插件--enable-java的AWT = GTK --enable-GTK开罗--with -java家庭= / usr / lib目录/ JVM / JAVA-1.5.0-的gcj-4.8-AMD64 / JRE --enable-java主--with-JVM的根目录= / usr / lib目录/ JVM / JAVA -1.5.0-GCJ-4.8-amd64的--with-JVM-JAR-DIR = / usr / lib目录/ JVM出口/ JAVA-1.5.0-的gcj-4.8-amd64的--with拱目录= AMD64 - -with-ECJ-JAR =的/ usr /股/ JAVA / Eclipse的ecj.jar --enable-objc-GC --enable-multiarch --disable-werror --with拱-32 = i686的--with-ABI = M64 --with-multilib的列表= M32,M64,MX32 --with调=通用--enable-检查=发行--build = x86_64的Linux的GNU的主机= x86_64的Linux的GNU的--target = x86_64的-Linux的GNU
线程模型:POSIX
gcc版本4.8.2(Ubuntu的4.8.2-19ubuntu1)
GCC
可以使用的内建函数在很多情况下的,他们的文件说:
许多这些功能是在某些情况下,仅进行了优化;如果他们
在特殊情况下不进行优化,以库函数的调用
被发射。
块引用>因此,因此
GCC
使用内建的功能时,将不再需要对数学库链接,但因为日志(0)
是没有定义 它可能迫使GCC
在运行时,以评估它,因为它具有副作用如果我们看一下草案C99标准部分
7.12.1
的处理错误条件的段落中的 4 的它说(的重点煤矿的):
一个浮动的结果溢出,如果数学的幅度
结果是有限的,但如此之大,数学结果不能
再$ P $不平凡的舍入误差在的对象psented
指定的类型。如果一个浮动的结果溢出和默认舍入
在效果,或者如果数学结果是从一个确切的无穷
有限的参数(例如日志(0.0)),则该函数返回
根据宏观HUGE_VAL,HUGE_VALF或HUGE_VALL的价值
返回类型,用相同的符号功能的正确值;
如果整型前pression math_errhandling&安培; MATH_ERRNO不为零,
整前pression错误号获取价值ERANGE; 如果整
前pression math_errhandling&安培; MATH_ERREXCEPT为非零值,
''除以零'浮点异常,如果募集
数学结果是一个确切的无穷大,'溢出'
浮点异常其他方式筹措。
块引用>我们可以使用
-S
标志产生组装和的grep的日志
过滤掉呼叫的活生生的例子见到日志
。在
日志的情况下(0.0)
产生下面的指令(的看直播 的):通话记录
但在
日志(10.0)
没有通话记录
产生指令,(的 <的情况下A HREF =http://coliru.stacked-crooked.com/a/d920d8447b7416d5>看直播 的)。我们通常可以prevent
GCC
使用内建函数使用的 - FNO,内置标志这可能是测试是否正在使用一个内置一个更快的方法注意
-lm
所需要的源文件一后走>,例如(从链接答案采取的),如果的main.c
所需的数学库,那么你可以使用:GCC的main.c -lm
For the following C source code:
#include <math.h> int main(void) { double x; x = log(0.0); return 0; }
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
But, if I replace
log(0.0)
withlog(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?
Just in case, my
gcc -v
output: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)
解决方案
gcc
can use builtin functions in many cases, their documentation says: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.
so therefore
gcc
will not need to link against the math library when using the builtin function but sincelog(0)
is not defined it probably forcesgcc
to evaluate it at run-time since it has a side effect.If we look at the draft C99 standard section
7.12.1
Treatment of error conditions in paragraph 4 it says (emphasis mine):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.
We can see from a live example using
-S
flag to generate assembly andgrep log
to filter out calls tolog
.In the case of
log(0.0)
the following instruction is generated (see it live):call log
but in the case of
log(10.0)
nocall log
instruction is generated, (see it live).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.Note that
-lm
needs to go after the source file, for example (taken from linked answer) ifmain.c
required the math library then you would use:gcc main.c -lm
这篇关于日志(10.0)可以编译,但日志(0.0)不能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!