日志功能不当行为!任何线索?

Mic*_*nel 2 c c++ visual-studio-2005 visual-c++

我正在用C编写一些程序.它有一个部分用于进行一些概率计算,我使用的是log函数.普通库函数log()...

代码是这样的

double somevalue = 0.29558101472995091;
temp = log(somevalue)
Run Code Online (Sandbox Code Playgroud)

你猜怎么着?温度值-1856.0000000000000 !!!

由于log给出的值在某个结构中,我也编写了这个测试代码,得到了相同的结果......

int main()
{
    double somevalue;
    double temp;

    somevalue = 0.29558101472995091;
    temp = log(somevalue);
    return 0;
}

Results:
Somevalue = 0.29558101472995091
temp = -1856.0000000000000
Run Code Online (Sandbox Code Playgroud)

不是很疯狂.任何人都有一些关于这里发生什么的线索.

我正在使用Visual Studio 2005.现在无法掌握其他编译器.

谢谢,

微内核:)

Mic*_*urr 8

您需要#include <math.h>这样编译器才能log()正确调用.

使用VC10,我得到以下结果printf ("log(%lf) = %lf\n", somevalue, temp )时,math.h包括:

log(0.295581) = -1.218812
Run Code Online (Sandbox Code Playgroud)

如果math.h不包括在内,我得到:

log(0.295581) = -1856.000000
Run Code Online (Sandbox Code Playgroud)

什么是可能发生的是,编译器期望从调用返回的值log()int然后将其转化为double对存储temp.我不知道编译器如何返回浮点结果,但我猜它们会在FP(0)寄存器中返回,而在EAX中返回一个int结果(假设是x86) Win32平台).因此,在这种情况下,编译器的值可能与log()函数尝试返回的值没有任何关系.

如果您将警告级别设置为/W3您将收到有关该问题的警告:

C:\TEMP\test.c(10) : warning C4013: 'log' undefined; assuming extern returning int
Run Code Online (Sandbox Code Playgroud)

在我看来,除非你正在使用一个没有利用函数原型的旧代码库,否则将该警告转换为错误可能是有道理的(当然,当编译为C++时这已经是一个错误) :

#pragma warning( error : 4013) // or use the `/we4013` compiler option
Run Code Online (Sandbox Code Playgroud)

这是可编译的测试:

#include <stdio.h>
//#include <math.h>

int main()
{
    double somevalue;
    double temp;

    somevalue = 0.29558101472995091;
    temp = log(somevalue);

    printf ("log(%lf) = %lf\n", somevalue, temp);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 实际上,它比这更糟糕.如果假设返回类型是和`int`而不是`double`,那么甚至不会将`double`读作`int`; 甚至可以从错误的地方读取返回值.IIRC,浮点值在许多x86调用约定中以'%st(0)`返回,而整数返回值在`%eax`中返回,因此它可能是随机垃圾,被读作`int`返回. (2认同)