gcc连接器的奇异数值行为
我对简单的C代码有如下问题:gcc连接器的奇异数值行为,c,gcc,linker,C,Gcc,Linker,我对简单的C代码有如下问题: #include <math.h> #include <stdio.h> int main () { printf ("%f\n", exp(1)); } 我使用以下bash脚本对1000以下的数字进行了测试: for i in {0..1000}; do sed -i -r "s:[0-9]+:${i}:" test.c gcc -o test test.c ./test done 将printf语句与
#include <math.h>
#include <stdio.h>
int main () {
printf ("%f\n", exp(1));
}
我使用以下bash脚本对1000以下的数字进行了测试:
for i in {0..1000}; do
sed -i -r "s:[0-9]+:${i}:" test.c
gcc -o test test.c
./test
done
将printf
语句与索引变量的exp
放在for循环中会导致相同的链接错误,而不考虑上限
这是怎么回事?编译器是否将710识别为长双精度的某种限制?那么为什么链接器会捕获错误?对不起,我不太懂C。我的猜测是,对于较小的数字,GCC编译器会将调用优化为其他内容,但是对于较大的数字,它需要数学库中的标准实现。数学库需要显式链接到
通过在链接时添加选项-lm
,可以链接到数学库。是选项-l
(小写l)告诉链接器链接到库,对于math库是m
关于可能的优化,您可以用一个小号码调用它,然后使用反汇编程序检查生成的代码。侧注:
exp
接受double
,不是long double
。您使用的是哪种编译器和哪个版本?请注意,如果您在C代码中使用变量作为exp()
的参数编写了一个循环,则必须从一开始就链接到数学库(-lm
,必要时;在macOS上不需要)。我尝试过,但无法在gcc 6.3.0上复制此错误。给定程序打印2.718282
。没有错误。我遗漏了什么?我使用的是gcc(Ubuntu 5.4.0-6ubuntu1~16.04.4)5.4.0 20160609
似乎你是对的,除非参数大于~709
,否则结果是在编译时计算的。exp(710)
大于典型实现中可以表示的最高有限数double,这意味着它将不得不报告一个范围错误,因此编译器将其留给库实现来处理。
for i in {0..1000}; do
sed -i -r "s:[0-9]+:${i}:" test.c
gcc -o test test.c
./test
done