Why does gcc report "implicit declaration of function ‘round’"? - c

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.

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.

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__));

You need to tell gcc that you want C99, and that you want to link in libm:
gcc -std=c99 -lm round_test.c

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'?

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.

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

Related

Glibc - error in ucontext.h, but only with -std=c11

I have this minimal helloworld, extended with an include of ucontext.h:
#include <ucontext.h>
#include <stdio.h>
int main(int argc, char** argv) {
printf ("hello world!\n");
return 0;
}
It compiles without warning with gcc-4.9 (gcc -c hw.c -Wall).
But if I switch to the c11 standard (gcc -std=c11 -c hw.c -Wall), I get the following error:
$ gcc -std=c11 -c hw.c -Wall
In file included from /usr/include/ucontext.h:26:0,
from hw.c:1:
/usr/include/x86_64-linux-gnu/sys/ucontext.h:137:5: error: unknown type name ‘stack_t’
stack_t uc_stack;
^
My first idea is that glibc doesn't support c11. Googling for that didn't reveal usable information. What is the case?
(I use glibc-2.19 with gcc-4.9. It is a debian jessie, amd64.)
-std=c11 is C11 standard compliant mode. <ucontext.h> isn't strictly part of C11 (see Stas's answer).
To use these headers either use extension mode -std=gnu11 or define appropriate macro depending on which platform do you intend to support (_POSIX_C_SOURCE, _BSD_SOURCE, _XOPEN_SOURCE, _GNU_SOURCE or maybe others).
See this page for more info about feature-enabling macros.
It seems <ucontext.h> functions are deprecated, because they use deprecated C feature. So they can't be used in standard compliant C code. See the rationale:
With the incorporation of the ISO/IEC 9899:1999 standard into this
specification it was found that the ISO C standard (Subclause 6.11.6)
specifies that the use of function declarators with empty parentheses
is an obsolescent feature. Therefore, using the function prototype:
void makecontext(ucontext_t *ucp, void (*func)(), int argc, ...);
is making use of an obsolescent feature of the ISO C standard.
Therefore, a strictly conforming POSIX application cannot use this
form. Therefore, use of getcontext(), makecontext(), and swapcontext()
is marked obsolescent.
So, it is not directly related to C11. For example, I can't compile your example with clang on Mac OS X at all.
It was deprecated in C99 standard:
6.11.6 Function declarators
The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an
obsolescent feature.

MinGW doesn't produce warnings

I have successfully installed MinGW on a Windows 7 32bit machine, and have tried to compile a simple program using either the command line or the MinGW console.
The code has an intentional error in a printf statement:
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
printf("%d\n" , 3.14 ) ;
return 0 ;
}
The command gcc -Wall hello.c gives a correct warning: hello.c:7:2: warning: format '%d' expects argument of type 'int'...
But the command gcc -std=c99 -Wall hello.c doesn't give any warning.
Both create an executable a.exe ( that runs and gives the same result ).
(Interestingly a command gcc -std=gnu99 -Wall hello.c gives the warning.)
I don't know if this is a bug, or did the installation go wrong somehow, but both seem unlikely since the compiler works and successfully compiled a larger project( but the same warning of course omitted when using -std=c99 ).
I must be missing some information.
(ps: If someone has a new MinGW install, please test this.)
gcc version 4.8.1 (GCC)
Update 1:
Defining _GNU_SOURCE before including stdio.h removes the warning even with gcc -Wall hello.c.
Update 2( might be less relevant ):
Compiling
printf("%lf\n" , 3.14 ) ;
-std=c99 flag outputs: 0.000000
-std=gnu99 outputs: 3.140000
And compiling:
printf("%f\n" , 3.14 ) ;
-std=gnu99 and -std=c99 output: 3.140000
Update 3:
Functions that seem to be affected are: printf, fprintf, snprintf, sprintf.
The problem with the lack of warning when using the std=c99 option looks like it's because MinGW 4.8.1 preprocesses stdio.h a little different for the printf() family of functions when -std=c99 is used compared to when -std=gnu99 is used.
Note: I'm looking at MinGW 4.8.1 from TDM - I think other distributions might differ in these details.
MinGW has had some compatibility issues with formatting floating point values because of its historic reliance on msvcrt.dll for the C runtime and the fact that MSVC uses a 64-bit representation for long double while gcc uses a 96-bit (or 128-bit on x64) representation. See gcc: printf and long double leads to wrong output. [C - Type conversion messes up] for some details. More recent versions of MinGW have provided thier own implementation of the printf() family of functions (with a __mingw_ prefix on the name) in libmingwex.a to solve those problems.
The header files _mingw.h and stdio.h configure whether or not the libmingwex.a implementations or the msvcrt.dll implementations will be used.
It appears that if ANSI compliance is requested, MinGW will use the libmingwex.a implementations (there are a number of other ways to get this configuration too - look at the headers for details). Wiring up a user call to printf() to the __mingw_printf() implementation in libmingwex.a is done by stdio.h defining a static inline implementation of printf() that is a thin wrapper around a call to __mingw_vfprintf(). Apparently the -Wformat doesn't get applied to versions of printf() family functions that the compiler doesn't believe to be part of the library (a reasonable assumption - the compiler doesn't really know anything about those functions). This problem can be fixed by applying the appropriate function attribute (for example: __attribute__ ((format (printf, 1, 2)))) to the static inline wrapper functions.
The other problem you found, where printf("%lf\n", 3.14) prints 0.000000 when using std=c99, looks to be a bug in the libmingwex.a implementation of __mingw_vfprintf(). It seems that __mingw_vfprintf() mistakenly interprets "%lf" to mean the argument is a long double. I'm not too surprised by that - I always have to look up whether %lf means double or long double.

What is the version of C used in gcc

What is the version of C used in GCC? C99, C11 or C90? I thought was the GCC use C99 but I was mistaken:
for(int i = 0; i < 100; i++){
...
}
error: ‘for’ loop initial declarations are only allowed in C99 mode.
According to 2 Language Standards Supported by GCC:
The default, if no C language dialect options are given, is -std=gnu90; this is intended to change to -std=gnu11 in some future release.
I believe the default is -std=gnu90. You could specify -std=c99 in your compiler flag to support this.
By default gcc uses C90 with GNU extension, this is all covered in the gcc docs Language Standards Supported by GCC, the flag for this would be -std=gnu90:
The default, if no C language dialect options are given, is -std=gnu90; this is intended to change to -std=gnu11 in some future release.
If you want C99 support than you should use -std=c99, although this does not mean gcc will not use extensions, so if you want to receive a warning when gcc using an extension you need to add -pedantic and -pedantic-errors to turn that into an error:
to obtain all the diagnostics required by the standard, you should also specify -pedantic (or -pedantic-errors if you want them to be errors rather than warnings)
Use -std=99
Before C99, you had to define the local variables at the start of a block. C99 imported the C++ feature that you can intermix local variable definitions with the instructions and you can define variables in the for and while control expressions.

Why gcc gives warning: implicit declaration of function qsort_r?

I do include<stdlib.h> where qsort_r is given. And I use gcc -std=c99 -O3 myfun.c -o myfun to compile.
It compiles, links and runs well. I don't know why I got this warning and what is potential risk of this warning ?
BTW, my compiler is gcc version 4.7.3 (Ubuntu/Linaro 4.7.3-1ubuntu1)
It does so because you use -std=c99 , there's no qsort_r function in stdlib.h in c99.
Use -std=gnu99 to make the extensions available, or add a #define _GNU_SOURCE to your source files before including the header files.
qsort_r is not supported by C99. Specification says nothing about it.
Language Standards Supported by GCC:
By default, GCC provides some extensions to the C language that on rare occasions conflict with the C standard1. 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.
1. Emphasis is mine

Why can't I use //-style comments in my C code?

I am using gcc (Ubuntu 4.4.1-4ubuntu9) to compile a program that I'm writing, but it seems to vomit whenever it sees a // comment in my code, saying:
interface.c :##: error: expected expression before â/â token<
Does the gcc compile mode I'm using forbid // comments?
$ gcc -g -ansi -pedantic interface.c structs.h -c -I. -I/home/me/project/h
Why?
// comments are not allowed in old (pre 99) C versions, use /**/ (or remove the -ansi, that is a synonym for the C89 standard)
See C++ comments in GNU compiler documentation.
In GNU C, you may use C++ style comments, which start with // and continue until the end of the line. Many other C implementations allow such comments, and they are included in the 1999 C standard. However, C++ style comments are not recognized if you specify an -std option specifying a version of ISO C before C99, or -ansi (equivalent to -std=c89).
(Emphasis is mine because some of the posts claim that // are not allowed in standard C whereas that is only true for pre-99 standards).

Resources