unistd.h and c99 on Linux - c

This simple .c file:
#include <unistd.h>
void test() {
char string[40];
gethostname(string,40);
}
... when compiled normally, works fine:
$ cc -Wall -c -o tmp.o tmp.c
$
... but when compiled in C99 mode, gives a warning:
$ cc -Wall -std=c99 -c -o tmp.o tmp.c
tmp.c: In function `test':
tmp.c:5: warning: implicit declaration of function `gethostname'
$
The resultant .o file is fine, and linking works. I'd just like to get rid of the warning. I can achieve this in a hacky way, by putting declarations in my own .h file.
What is it about C99 that means the declarations in unistd.h don't get included?
Can this be overcome, without giving up the niceness of C99?
I see the same problem for other standard libs.

You may need to define some macros in a particluar way to get the prototype for gethostname()
From man gethostname:
Feature Test Macro Requirements for
glibc (see feature_test_macros(7)):
gethostname(): _BSD_SOURCE || _XOPEN_SOURCE >= 500
sethostname(): _BSD_SOURCE || (_XOPEN_SOURCE && _XOPEN_SOURCE < 500)
So:
#define _BSD_SOURCE
#include <unistd.h>
void test() {
char string[40];
gethostname(string,40);
}
The gory details:
If you don't specify the -std-c99 option, then features.h (which is implicitly included by unistd.h) will default to setting _BSD_SOURCE in such a way that the prototype for gethostname() gets included. However, specifying -std=c99 causes the compiler to automatically define __STRICT_ANSI__, which in turn causes features.h to not define _BSD_SOURCE, unless you force it with your own feature macro definition (as above).

gethostname( ) is not a standard C function (it's not mentioned anywhere in the C99 standard), so the symbol is correctly not defined when compiling to the standard.
If you're using the gcc toolchain, use -std=gnu99 and you'll get the behavior you want.
Alternatively, looking at <features.h>, it seems like you could use -D_GNU_SOURCE or -D_XOPEN_SOURCE=500 to get the desired behavior.

Read man gethostname. It says in the Feature Test Macro Requirements, that _BSD_SOURCE (or _XOPEN_SOURCE>500) is required to pull gethostname from unistd.h.
Next read man feature_test_macros. You will find that -std=c99 turns on __STRICT_ANSI__ which in turns off _BSD_SOURCE. This means you can't get gethostname from unistd.h unless you define _BSD_SOURCE again. I usually place _GNU_SOURCE on my command line (i.e. gcc -D_GNU_SOURCE -std=c99 file.c) for most things, which turns on _BSD_SOURCE as well.
P.S. The manual page contains an example program which can print the current ft-macros. You might compile and run it for some compiler settings.

Related

undefined reference to `CreateRGBABitmapImageReference' [duplicate]

I would like to compile this.
program.c
#include <libavcodec/avcodec.h>
int main(){
int i = avpicture_get_size(AV_PIX_FMT_RGB24,300,300);
}
Running this
gcc -I$HOME/ffmpeg/include program.c
gives error
/tmp/ccxMLBme.o: In function `main':
program.c:(.text+0x18): undefined reference to `avpicture_get_size'
collect2: ld returned 1 exit status
However, avpicture_get_size is defined. Why is this happening?
However, avpicture_get_size is defined.
No, as the header (<libavcodec/avcodec.h>) just declares it.
The definition is in the library itself.
So you might like to add the linker option to link libavcodec when invoking gcc:
-lavcodec
Please also note that libraries need to be specified on the command line after the files needing them:
gcc -I$HOME/ffmpeg/include program.c -lavcodec
Not like this:
gcc -lavcodec -I$HOME/ffmpeg/include program.c
Referring to Wyzard's comment, the complete command might look like this:
gcc -I$HOME/ffmpeg/include program.c -L$HOME/ffmpeg/lib -lavcodec
For libraries not stored in the linkers standard location the option -L specifies an additional search path to lookup libraries specified using the -l option, that is libavcodec.x.y.z in this case.
For a detailed reference on GCC's linker option, please read here.
Are you mixing C and C++? One issue that can occur is that the declarations in the .h file for a .c file need to be surrounded by:
#if defined(__cplusplus)
extern "C" { // Make sure we have C-declarations in C++ programs
#endif
and:
#if defined(__cplusplus)
}
#endif
Note: if unable / unwilling to modify the .h file(s) in question, you can surround their inclusion with extern "C":
extern "C" {
#include <abc.h>
} //extern

No GCC warning for function with declaration different from definition

C file definition:
#include <stdint.h>
void foo(int i)
{
if(i>0) bar();
}
H file declaration:
#ifndef FILE_H
#define FILE_H
void foo(void);
#endif FILE_H
main:
#include "file.h"
int main(void)
{
foo();
}
The file.h is not included in file.c for some abstraction reasons.
Why isn't GCC generating any warning in this particular case?
As noted in comments…
In general terms, you must include the header that declares a function both where the function is defined and where it is used. You didn't, so the compiler couldn't warn. Headers are the glue that allow the compiler to do the cross-checking necessary to ensure basic sanity in your code.
The question claims:
The file.h is not included in file.c for some abstraction reasons.
It isn't clear what those abstraction reasons are, but whatever the reasoning, it is faulty. Since the question does not (yet) specify in any more detail what the problem is, we can't help you fix the issues. However, they're spurious — you are doing something wrong.
Specifically, you must include file.h in file.c as well as inmain.c. Otherwise, you don't get the cross-checking you need — or the warning you desire. You also need a prototype for bar() in file.c — you shouldn't be calling a function without a prototype (strictly, a non-prototype declaration is sufficient, but you really want a prototype) in scope, and there's no prototype for bar() in either <stdint.h> or file.h.
I compile using GCC and options:
gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes …
I don't bother to run the code until that's clean — indeed, the -Werror means I can't run the code until that's clean because the compilation fails if there is any warning or error. You can afford to go more stringent if you prefer; you shouldn't risk going much less stringent than that.
Note that both C99 and C11 require that a function is declared or defined before it is used. Only the ancient C90 standard permits calling functions that have not been pre-declared or pre-defined.

How a standard library differ from user defined header file (.h) and its implementation file (.c) in C?

How a standard library like libc.a (static library) which is included using #include <stdio.h> in our main.c differ from user defined header file (cube.h) included in main.c with its implementation file (cube.c) in C ?
I mean both are header files but one's implementation is a static library (.a) and others is source file (.c) .
You would have the definition (implementation) in, say, cube.c
#include "cube.h"
int cube( int x ) {
return x * x * x;
}
Then we'll put the function declaration in another file. By convention, this is done in a header file, cube.h in this case.
int cube( int x );
We can now call the function from somewhere else, main.c for instance, by using the #include directive (which is part of the C preprocessor) .
#include "cube.h"
#include <stdio.h>
int main() {
int c = cube( 10 );
printf("%d", c);
...
}
Also if I included include guards in cube.h what would happen when I include cube.h in both main.c and cube.c . Where it will get included?
A programming language is not the same as its implementation.
A programming language is a specification (written on paper; you should read n1570, which practically is the C11 standard), it is not a software. The C standard specifies a C standard library and defines the headers to be #include-d.
(you could run your C program with a bunch of human slaves and without any computers; that would be very unethical; you could also use some interpreter like Ch and avoid any compiler or object or executable files)
How a standard library like libc.a (static library) which is included using #include <stdio.h> ... differs from a user file cube.c
The above sentence is utterly wrong (and makes no sense). libc.a does not #include -or is not included by- the <stdio.h> header (i.e. file /usr/include/stdio.h and other internal headers e.g. /usr/include/bits/stdio2.h). That inclusion happens when you compile your main.c or cube.c.
In principle, <stdio.h> might not be any file on your computer (e.g. #include <stdio.h> could trigger some magic in your compiler). In practice, the compiler is parsing /usr/include/stdio.h (and other included files) when you #include <stdio.h>.
Some standard headers (notably <setjmp.h>, <stdreturn.h>, <stdarg.h>, ....) are specified by the standard but are implemented with the help of special builtins or attributes (that is "magic" things) of the GCC compiler.
The C standard knows about translation units.
Your GCC compiler processes source files (grossly speaking, implementing translation units) and starts with a preprocessing phase (processing #include and other directives and expanding macros). And gcc runs not only the compiler proper (some cc1) but also the assembler as and the linker ld (read Levine's Linkers and Loaders book for more).
For good reasons, your header file cube.h should practically start with include guards. In your simplistic example they are probably useless (but you should get that habit).
You practically should almost always use gcc -Wall -Wextra -g (to get all warnings and debug info). Read the chapter about Invoking GCC.
You may pass also -v to gcc to understand what programs (e.g. cc1, ld, as) are actually run.
You may pass -H to gcc to understand what source files are included during preprocessing phase. You can also get the preprocessed form of cube.c as the cube.i file obtained with gcc -C -E cube.c > cube.i and later look into that cube.i file with some editor or pager.
You -or gcc- would need (in your example) to compile cube.c (the translation unit given by that file and every header files it is #include-ing) into the cube.o object file (assuming a Linux system). You would also compile main.c into main.o. At last gcc would link cube.o, main.o, some startup files (read about crt0) and the libc.so shared library (implementing the POSIX C standard library specification and a bit more) to produce an executable. Relocatable object files, shared libraries (and static libraries, if you use some) and executables use the ELF file format on Linux.
If you code a C program with several source files (and translation units) you practically should use a build automation tool like GNU make.
If I included include guards in cube.h what would happen when I include cube.h in both main.c and cube.c ?
These should be two different translation units. And you would compile them in several steps. First you compile main.c into main.o using
gcc -Wall -Wextra -g -c main.c
and the above command is producing a main.o object file (with the help of cc1 and as)
Then you compile (another translation unit) cube.c using
gcc -Wall -Wextra -g -c cube.c
hence obtaining cube.o
(notice that adding include guards in your cube.h don't change the fact that it would be read twice, once when compiling cube.c and the other time when compiling main.c)
At last you link both object files into yourprog executable using
gcc -Wall -Wextra -g cube.o main.o -o yourprog
(I invite you to try all these commands, and also to try them with gcc -v instead of gcc above).
Notice that gcc -Wall -Wextra -g cube.c main.c -o yourprog is running all the steps above (check with gcc -v). You really should write a Makefile to avoid typing all these commands (and just compile using make, or even better make -j to run compilation in parallel).
Finally you can run your executable using ./yourprog (but read about PATH), but you should learn how to use gdb and try gdb ./yourprog.
Where it cube.h will get included?
It will get included at both translation units; once when running gcc -Wall -Wextra -g -c main.c and another time when running gcc -Wall -Wextra -g -c cube.c. Notice that object files (cube.o and main.o) don't contain included headers. Their debug information (in DWARF format) retains that inclusion (e.g. the included path, not the content of the header file).
BTW, look into existing free software projects (and study some of their source code, at least for inspiration). You might look into GNU glibc or musl-libc to understand what a C standard library really contains on Linux (it is built above system calls, listed in syscalls(2), provided and implemented by the Linux kernel). For example printf would ultimately sometimes use write(2) but it is buffering (see fflush(3)).
PS. Perhaps you dream of programming languages (like Ocaml, Go, ...) knowing about modules. C is not one.
TL;DR: the most crucial difference between the C standard library and your library function is that the compiler might intimately know what the standard library functions do without seeing their definition.
First of all, there are 2 kinds of libraries:
The C standard library (and possibly other libraries that are part of the C implementation, like libgcc)
Any other libraries - which includes all those other libraries in /usr/lib, /lib, etc.., or those in your project.
The most crucial difference between a library in category 1 and a library in category 2 library is that the compiler is allowed to assume that every single identifier that you use from category 1 library behaves as if it is the standard library function and behaves as if in the standard and can use this fact to optimize things as it sees fit - this even without it actually linking against the relevant routine from the standard library, or executing it at the runtime. Look at this example:
% cat foo.c
#include <math.h>
#include <stdio.h>
int main(void) {
printf("%f\n", sqrt(4.0));
}
We compile it, and run:
% gcc foo.c -Wall -Werror
% ./a.out
2.000000
%
and correct result is printed out.
So what happens when we ask the user for the number:
% cat foo.c
#include <math.h>
#include <stdio.h>
int main(void) {
double n;
scanf("%lf\n", &n);
printf("%f\n", sqrt(n));
}
then we compile the program:
% gcc foo.c -Wall -Werror
/tmp/ccTipZ5Q.o: In function `main':
foo.c:(.text+0x3d): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status
Surprise, it doesn't link. That is because sqrt is in the math library -lm and you need to link against it to get the definition. But how did it work in the first place? Because the C compiler is free to assume that any function from standard library behaves as if it was as written in the standard, so it can optimize all invocations to it out; this even when we weren't using any -O switches.
Notice that it isn't even necessary to include the header. C11 7.1.4p2 allows this:
Provided that a library function can be declared without reference to any type defined in a header, it is also permissible to declare the function and use it without including its associated header.
Therefore in the following program, the compiler can still assume that the sqrt is the one from the standard library, and the behaviour here is still conforming:
% cat foo.c
int printf(const char * restrict format, ...);
double sqrt(double x);
int main(void) {
printf("%f\n", sqrt(4.0));
}
% gcc foo.c -std=c11 -pedantic -Wall -Werror
% ./a.out
2.000000
If you drop the prototype for sqrt, and compile the program,
int printf(const char * restrict format, ...);
int main(void) {
printf("%f\n", sqrt(4));
}
A conforming C99, C11 compiler must diagnose constraint violation for implicit function declaration. The program is now an invalid program, but it still compiles (the C standard allows that too). GCC still calculates sqrt(4) at compilation time. Notice that we use int here instead of double, so it wouldn't even work at runtime without proper declaration for an ordinary function because without prototype the compiler wouldn't know that the argument must be double and not the int that was passed in (without a prototype, the compiler doesn't know that the int must be converted to a double). But it still works.
% gcc foo.c -std=c11 -pedantic
foo.c: In function ‘main’:
foo.c:4:20: warning: implicit declaration of function ‘sqrt’
[-Wimplicit-function-declaration]
printf("%f\n", sqrt(4));
^~~~
foo.c:4:20: warning: incompatible implicit declaration of built-in function ‘sqrt’
foo.c:4:20: note: include ‘<math.h>’ or provide a declaration of ‘sqrt’
% ./a.out
2.000000
This is because an implicit function declaration is one with external linkage, and C standard says this (C11 7.1.3):
[...] All identifiers with external linkage in any of the following subclauses (including the future library directions) and errno are always reserved for use as identifiers with external linkage. [...]
and Appendix J.2. explicitly lists as undefined behaviour:
[...] The program declares or defines a reserved identifier, other than as allowed by 7.1.4 (7.1.3).
I.e. if the program did actually have its own sqrt then the behaviour is simply undefined, because the compiler can assume that the sqrt is the standard-conforming one.

What default libraries are taken while compiling C project with GCC

I have simple application:
#include <stdio.h>
int main( int argc, char ** argv )
{
printf( "hello");
exit( 0 );
}
When I compile it with command
gcc -c count_words.c
I have warning:
warning: incompatible implicit declaration of built-in function ‘exit’ [enabled by default]
exit( 0 );
I was trying to find where exit() function is defined. And found that it is defined in stdlib.h. But it is not included in my project and no additional libs defined in compile command.
Correct me if I'm wrong, but looks like gcc takes some libs as default. What are these libs and is it possible to tell gcc not include them?
Why compiler is not happy regarding exit(0) assuming that it somehow includes stdlib.h as default?
Let's take your example:
#include <stdio.h>
int main( int argc, char ** argv )
{
printf("hello\n");
exit(56);
}
Although we get a warning on compilation:
~$ gcc test.c -o test
test.c: In function ‘main’:
test.c:6:5: warning: implicit declaration of function ‘exit’ [-Wimplicit-function-declaration]
exit(56);
^
test.c:6:5: warning: incompatible implicit declaration of built-in function ‘exit’
test.c:6:5: note: include ‘<stdlib.h>’ or provide a declaration of ‘exit’
Anyway, I think you have tried to run it and make sure it works:
~$ ./test
hello
~$ echo $?
56
#Mat was right when he said that:
You're mixing up including headers and linking to libraries. Those are
two completely different things
The C compiler and linker are totally separate tools. Let's look on this. Actually, this program depends on the standard C library (as all programs if you didn't pass -nostdlib to compiler) and a couple of system libraries (like loader and vdso). You may see it with:
~$ ldd test
linux-vdso.so.1 (0x00007fff1b128000)
libc.so.6 => /lib64/libc.so.6 (0x00007f804389f000)
/lib64/ld-linux-x86-64.so.2 (0x0000557744537000)
These three library is a minimal set for any program. The exit function is defined in the standard library or libc.so.6 in our case. Now let's look on the compilation process in verbose mode. You can achieve this by the passing -v or --verbose option to compiler:
gcc test.c -o test --verbose
If you will execute this, you will find lines like these:
#include <...> search starts here:
/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include
/usr/local/include
/usr/include
So, compile knows where to search header files for stdlib and it starts to search it to find declaration for non-local functions. Note that it searches only in header files which are included in your source code file. It can find printf declaration in thestdio.h, but can't locate declaration of the exit.
After this step, the compile starts to link your program with libraries:
/usr/libexec/gcc/x86_64-redhat-linux/5.3.1/collect2 ... -lc ...
Where collect2 is gcc util which tries to link your program with lc which is standard C library. Note that the process consists from two steps: compilation and linking. That's why your program works.
Additionally, gcc supports -M option which will tell you about dependencies of the main file. So, if you will execute it, you will see the set of header files including stdio.h, but not stdlib.h:
$ gcc -M test.c
test.o: test.c /usr/include/stdc-predef.h /usr/include/stdio.h \
/usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
/usr/include/gnu/stubs-64.h \
/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stddef.h \
/usr/include/bits/types.h /usr/include/bits/typesizes.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stdarg.h \
/usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
Or even better, try to pass -E option to gcc:
$ gcc -E test.c
and you will see result right after the first stage - preprocessing stage. I think it is the easiest way to understand why you are getting this warning.
assuming that it somehow includes stdlib.h as default?
It simply doesn't. That wouldn't be standards-compliant.
So, when you use exit, it has never been declared, so there's you implicit declaration upon usage. However, the fact to you implement exit nowhere else will only become a problem at the final linkage.
Now, GCC knows damn well that you are about to get into trouble, so it warns you.
Simply actually include stdlib.h and you should be fine.
The "library" in question is gcc/builtins.def from the gcc source tree.
That's not just a header file though, and it does not provide declarations for you to use. But it has proper prototypes to check yours against.
Calling undeclared exit() results in implicit declaration like this:
int exit(int);
Search "c implicit declarations" for the gory details. In this case however GCC has its own prototype for exit() from builtins.def:
void exit(int) __attribute__((nothrow,noreturn));
These declarations do not match, and that's what you are being warned about.
Your code works with warning not with error. If you add
#include <stdlib.h>
then no warning anymore ;)

Why can't gcc find the random() interface when -std=c99 is set?

I do "#include <stdlib.h>" at the top of the source.
Example compilation:
/usr/bin/colorgcc -std=c99 -fgnu89-inline -g -Wall -I/usr/include -I./ -I../ -I../../ -I../../../ -I../../../../ -O3 -o f8 f8.c
In file included from f8.c:7:
ctype-cmp.c: In function ‘randomized’:
ctype-cmp.c:48: warning: implicit declaration of function ‘random’
ctype-cmp.c: In function ‘main’:
ctype-cmp.c:153: warning: implicit declaration of function ‘srandom’
ais#xcalibur:t$
When I turn off -std=c99, the function isfinite() can not be found. So I do want to use -std=c99 for this and other reasons. Is there some trick I'm missing?
man srandom says that the function is not part of C99 but part of POSIX.
Activate _BSD_SOURCE or _XOPEN_SOURCE >= 500 or any other suitable feature test macro that declares the srandom/random function (see man feature_test_macros and man srandom).
This one has good chances, but you need to figure out the macros that are defined/not defined implicitly thereby too by reading the manpages above.
/usr/bin/colorgcc -std=c99 -D_XOPEN_SOURCE=600 -fgnu89-inline -g -Wall
-I/usr/include -I./ -I../ -I../../ -I../../../ -I../../../../ -O3 -o f8 f8.c
Yes, there is a trick you are missing: you can use -std=gnu99 instead of -std=c99.
-std=c99 #defines __STRICT_ANSI__, which /usr/include/features.h interprets as "do not enable anything outside the C standard by default" (without it, you get at least both _SVID_SOURCE and _BSD_SOURCE). -std=gnu99, on the other hand, means "C99 plus GNU extensions" (the gcc default is currently -std=gnu89, its C89 equivalent, which is why you needed to specify something to get the new C99 features).
As an alternative, you can enable the feature test macros (as mentioned in #litb's answer). Looking at /usr/include/stdlib.h in my system, it expects one of __USE_SVID, __USE_XOPEN_EXTENDED, or __USE_BSD. /usr/include/features.h tells me that the feature test macros which would enable these are:
_SVID_SOURCE (enables __USE_SVID)
_BSD_SOURCE (enables __USE_BSD)
_XOPEN_SOURCE with a value of at least 500 (enables __USE_XOPEN_EXTENDED)
_XOPEN_SOURCE_EXTENDED (also enables __USE_XOPEN_EXTENDED)
_GNU_SOURCE (enables everything, including the four feature test macros above)
For new programs where you are not too concerned about potential name collisions with new functions from future standards, using both -std=gnu99 and -D_GNU_SOURCE is a good idea. It allows you to use all the new standard features and GNU extensions, which combined with some sort of fallback (for instance, autoconf-style feature tests) gives the most flexibility.
References:
Options Controlling C Dialect
Feature Test Macros
I've created random numbers using gcc in CodeBlocks under Ubuntu 9.10 (with compiler options: -std=gnu99 -D_GNU_SOURCE) So this worked for me:
This is my code I had played with:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
enum computer {keyboard, CPU, screen, printer};
int main(void)
{
enum computer comp;
time_t casovac;
comp = CPU;
srand(&casovac);
printf("%d", rand());
return 0;
}
This was only idea, of course you can accomplish it by other ways ;-) [To install CodeBlocks use: sudo apt-get install build-essential and then sudo apt-get install codeblocks]
I use rand() and srand(). BTW: Did you forget a header or two? At least the second warning tells me so.
Try including math.h. (Just remembered we always had issues with math library and had to actually force link it with -lm).

Resources