views:

108

answers:

2

Hi guys,

I am writing some program in C. It has a part where it does some probability calculations, where I am using log function. normal library function log()...

The code is something like this

double somevalue = 0.29558101472995091;
temp = log(somevalue)

And guess what? The temp gets value -1856.0000000000000!!!

As the value given for log was inside some struct I wrote this test code too, and got the same results...

int main()
{
    double somevalue;
    double temp;

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

Results:
Somevalue = 0.29558101472995091
temp = -1856.0000000000000

Isn't it crazy. Anyone has some clue on whats going on here.

And I am using Visual Studio 2005 for this. Can't get my hands on someother compiler now.

Thanks,

Microkernel :)

A: 

Looks like your syntax is correct. How are you printing your results? If you're using a printf statement, make sure you have your format string correct.

It should go like in this example:

printf ("log(%lf) = %lf\n", somevalue, temp );
John at CashCommons
Na it gives -1.21881 to me with both cout and the above statement.
DumbCoder
-1.21881 is the correct output
John Dibling
No, I was using Watch window while stepping through the program... Thanks for the reply :)
Microkernel
+9  A: 

You need to #include <math.h> so the compiler will call log() correctly.

Using VC10, I get the following result from printf ("log(%lf) = %lf\n", somevalue, temp ) when math.h is included:

log(0.295581) = -1.218812

If math.h isn't included, I get:

log(0.295581) = -1856.000000

What's probably happening is that the compiler expects the returned value from the call to log() to be int which is then converted to a double to store in temp. I don't know off the top of my head how floating point results are returned by the compiler, but I'd guess they're returned in the FP(0) register, while an int result is returned in EAX (assuming an x86 Win32 platform). So the value to compiler gets in this case might not even have any relationship with the value the log() function tries to return.

If you set the warning level to /W3 you'll get a warning about the problem:

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

In my opinion, unless you're working with a really old codebase that doesn't take advantage of function prototypes, it might make good sense to turn that warning into an error (of course, when compiled as C++ this is already an error):

#pragma warning( error : 4013) // or use the `/we4013` compiler option

Here's the compilable test:

#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;
}
Michael Burr
This question shouldn't have the C++ tag then, since it doesn't allow calling an undeclared function with "implicit int".
Mark B
Wow!!!That really is the reason!!!I'm wondering what the compiler is doing then if it can't find the proper log function!!! I would have expected linker error if it can't find proper function....Hah, even after 2 years of coding in C, what a noob I am!!! Thanks Michael, it helped a lot!!! :)
Microkernel
@Microkernel I believe if you compiled it as C++ or even ANSI C this code wouldn't have compiled.
Mark B
It's almost certainly the return type, not the parameter type that is the issue. The `double` will be passed as a `double` to a function taking unknown arguments (which happens to be correct), but the return value will be assumed (incorrectly) to be an `int` which is then 'converted' the the `double` `temp`.
Charles Bailey
Why would someone put their warning level below the default? It *should* be at the /W4.
GMan
@Charle - you're right... I'll fix that.
Michael Burr
@Mark B, I used Visual Studio 2005 (created empty C project). isn't it ANSI-C?
Microkernel
Acutally, it's worse than that. If the return type is assumed to be and `int` rather than a `double` it's not even that the `double` is being read as an `int`; the return value could even be read from the wrong place. IIRC, floating point values are returned in `%st(0)` in many x86 calling conventions while integer return values are returned in `%eax` so it could be random rubbish that is being read as an `int` return.
Charles Bailey
@GMan: my VC10 compiler says that the default warning level for the compiler is 1. I mentioned level 3 because that's the level that C4013 starts showing up.
Michael Burr
@Microkernel Compilers (especially MS) often have compatibility features and extensions enabled by default. There may be an option you have to switch on to force strict ANSI compatibility. Or just enable `/W3` like Michael Burr says in the answer.
Mark B
@Microkernel - even in VC10, the MSVC compiler's C 'mode' is for ANSI C89/C90. In that version of the C standard, function declarations aren't required - a function call without a declaration will implicitly assume an `int` is returned and that parameters will be passed using default promotions. In C99 (which MSVC doesn't support), implicit function declarations are no longer supported.
Michael Burr
@Microkernel - also, as an FYI, by default MSVC will compile files that have a .c extension as C and .cpp files as C++. Look at the docs for the /Tp and /Tc (and related) options for more information.
Michael Burr