views:

1320

answers:

6

I have the following C code:

#include <math.h>

int main(int argc, char ** argv)
{
    double mydouble = 100.0;
    double whatever = round(mydouble);

    return (int) whatever;
}

When I compile this, I get the warnings:

round_test.c: In function ‘main’:
round_test.c:6: warning: implicit declaration of function ‘round’
round_test.c:6: warning: incompatible implicit declaration of built-in function ‘round’

I'm rusty with C, but I thought that the #include brought a declaration for round() into scope. I've checked my ANSI standard (C99 is the only copy I have) which confirms that the round() function exists in the math.h header. What am I missing here?

Edit: The compiler is GCC 4.3.2 on Ubuntu (intrepid, IIRC). Running gcc -E gives:

$ gcc -E round_test.c | grep round
# 1 "round_test.c"
# 1 "round_test.c"
# 2 "round_test.c" 2
    double whatever = round(mydouble);

so the definition obviously isn't being found in the headers.

+3  A: 

Something must be wrong with your gcc installation, system headers, or compilation options.

Try compiling with -E. That will show you what the preprocessor output -- including which headers are being included and what's in them. On my Ubuntu Linux system it's about 1000 lines of output, including this:

extern double round (double __x) __attribute__ ((__nothrow__)) __attribute__ ((__const__));
Jason Orendorff
I'm on Ubuntu 9.10 (Karmic). Here `#include <math.h>` loads /usr/include/math.h which loads /usr/include/bits/mathcalls.h which contains the declaration.
Jason Orendorff
A: 

The code you type compiles cleanly on MacOS X 10.5.8 with GCC 4.0.1. If prodded with options '-Wall -Wextra', it complains about unused parameters argc and argv - not material.

Have you looked in <math.h> on your machine?

Have you tried with options such as '-stc=c99'?

Jonathan Leffler
+8  A: 

I see you're using gcc.

By default, gcc uses a standard similar to C89. You may want to "force" it to use the C99 standard (the parts it complies with)

gcc -std=c99 -pedantic ...

Quote from GCC Manual

By default, GCC provides some extensions to the C language that on rare occasions conflict with the C standard. See Extensions to the C Language Family. Use of the -std options listed above will disable these extensions where they conflict with the C standard version selected. You may also select an extended version of the C language explicitly with -std=gnu89 (for C89 with GNU extensions) or -std=gnu99 (for C99 with GNU extensions). The default, if no C language dialect options are given, is -std=gnu89; this will change to -std=gnu99 in some future release when the C99 support is complete. Some features that are part of the C99 standard are accepted as extensions in C89 mode.

pmg
Thanks, -std=c99 seemed to solve it. I hadn't realised round() was a C99 addition (and of course all my references are C99 and neglect to mention this)
Tim
(surprised look) Is round() really a C99 addition?
Jason Orendorff
Right, C89 didn't describe the `round()` function (of course compilers could provide it as an extension).
pmg
Looks like it - from the Ubuntu 8.04 manpage - round(), roundf(), roundl(): _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE; or cc -std=c99
Douglas Leeder
Also need -lm to link libm to get the actual function.
Douglas Leeder
@Tim: if you want a text-only version of the C89 Standard look @ http://flash-gordon.me.uk/ansi.c.txt
pmg
+2  A: 

You need to tell gcc that you want C99, and that you want to link in libm:

gcc -std=c99 -lm round_test.c
Douglas Leeder
A: 

you need to link with the math library. So when you compile, be sure to add the -lm flag.

lorenzog
Thanks for the input, but this is a compile problem, not a link problem. I realised I left out my compiler command (my bad), but I was compiling with gcc -c.
Tim
A: 

C99 was the answer, but the full story is a little more complicated. The reason I'd been playing with this at all was that I was trying to compile a library written for Windows, which had its own "optimised" definition of round(). I got a linker error telling me that the definition conflicted with the built-in, so I removed the definition (and declaration). Once I'd done that I started to get the "implicit declaration error".

It seems that the default compile mode (without the -std=c99 flag) is neither conforming C89 nor C99: if it were conforming C89, you should be able to provide a custom definition of round() without conflicting, and if it were conforming C99 the declaration should be in math.h.

Tim
The default mode is `-std=gnu89` :)
pmg