What libc and can I omit it's includes in my project? - c

I have simple program without includes that compiles with some warnings:
int main(int argc, char **argv)
{
printf("hello");
exit(0);
}
Compile:
gcc hello.c
Warning:
In function ‘main’:
warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
printf("hello");
^
warning: incompatible implicit declaration of built-in function ‘exit’ [enabled by default]
exit( 0 );
^
compilation command is very simple and not contains information regarding include library files that contains printf and exit. Correct me if I'm wrong, but looks that gcc links my project to these libraries by default. That points me to thinking that include files of libc libraries is not required?
Correct me once again. I got warnings because GCC somehow knows some basic functions of libc and these functions has different params. But since GCC checks all libc it founds correct function anyway.
What is libc at all. Is it some standard set of binary object and header files?

looks that gcc links my project to these libraries by default. That points me to thinking that include files of libc libraries is not required?
Includes and linking are not related that way. The includes contain function prototypes that instruct the compiler about the return value type and parameters of a given function. When a function call happens, and there is no prototype for it yet the compiler assumes it returns int and that may lead to undefined behavior.
The program will be linked to the standard libraries and function definitions will be available, but since the program was compiled with the assumption that these functions all return int there can be runtime errors related to this, which cannot be predicted since the behavior is undefined.
I got warnings because GCC somehow knows some basic functions of libc and these functions has different params. But since GCC checks all libc it founds correct function anyway.
No, it has nothing to do with gcc knowing anything but the opposite, it has to do with gcc not knowing how to call these functions.
What is libc at all. Is it some standard set of binary object and header files?
libc is a binary file libc.so.6 in current glibc and it's the runtime library with all the symbols needed by a standard c program, it does not include math.h funcions for example (that is libm.so.6).
You still need header files in your c programs for the reasons explained above, or at least declarations of the standard functions you use. These declaration are called prototypes and are required by the compiler in order to correctly compile your code.
NOTE: Always compile with at least -Wall -Werror, like this
gcc -Wall -Werror hello.c

Related

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.

Does gcc include some header files automatically?

I have the following code:
int main()
{
printf("Hello\n");
return 0;
}
I compiled it using the following command:
gcc -o myprogram myfile.c
And it compiled without any error even though I did not #include <stdio.h>. So did gcc include this header file automatically?
My gcc version is 4.3.3
In ANSI C, you can call functions you didn't declare. Such functions are implicitly declared the first time you call them. They are assumed to return int and take arguments according to the default argument promotions. Since you didn't include <stdio.h>, the compiler uses this rule and implicitly declares printf. Note that this is undefined behaviour as functions that take variable argument lists like printf must be declared explicitly. gcc usually warns you if it uses the implicit declaration rule since it's usually not intentionally used.
No, gcc did not include any header files you didn't request. #include statements are C preprocessor macros (like #define or #if) that are actually evaluated before the actual C compilation. You can see what your code looks like after all macros are resolved by calling gcc -E myfile.c. As you will see, printf will still not be declared.
If you compile with -Wall, you should get a warning that printf is undeclared. However gcc "guesses" how printf is used (probably from its arguments, but it could also simply know the routine internally). Since it finds a matching symbol name while linking, you don't get an error and your program runs just fine.
BTW, gcc 5.3.0 shows the following warning:
myfile.c: In function 'main':
myfile.c:3:5: warning: implicit declaration of function 'printf' [-Wimplicit-function-declaration]
printf("Hello\n");
^
myfile.c:3:5: warning: incompatible implicit declaration of built-in function 'printf'
myfile.c:3:5: note: include '<stdio.h>' or provide a declaration of 'printf'

Why does this C program compile with no errors?

Locked. There are disputes about this question’s content being resolved at this time. It is not currently accepting new answers or interactions.
I have the two C files, main.c and weird.c:
// main.c
int weird(int *);
int
main(void)
{
int x, *y;
y = (int *)7;
x = weird(y);
printf("x = %d\n", x);
return (0);
}
// weird.c
char *weird = "weird";
However, when I run the following:
clang -Wall -Wextra -c main.c
clang -Wall -Wextra -c weird.c
clang -o program main.o weird.o
I do not get any errors. Why is this? Shouldn't there at least be linking errors? Note that I am just talking about compiling the files — not running them. Running gives a segmentation fault.
Should there be a linker error?
The short answer to "Shouldn't there at least be linking errors?" is "There is no guarantee that there'll be a linking error". The C standard doesn't mandate it.
As Raymond Chen noted in a comment:
The language-lawyer answer is that the standard does not require a diagnostic for this error. The practical answer is that C does not type-decorate symbols with external linkage, so the type mismatch goes undetected.
One of the reasons C++ has type-safe linkage is to avoid problems with code analogous to this (though the main reason is to allow for function name overloading — resolving this sort of problem is, perhaps, more a side-effect).
The C standard says:
§6.9 External definitions
¶5 An external definition is an external declaration that is also a definition of a function
(other than an inline definition) or an object. If an identifier declared with external
linkage is used in an expression (other than as part of the operand of a sizeof or
_Alignof operator whose result is an integer constant), somewhere in the entire
program there shall be exactly one external definition for the identifier; otherwise, there
shall be no more than one.
§5.1.1.1 Program structure
¶1 A C program need not all be translated at the same time. The text of the program is kept in units called source files, (or preprocessing files) in this International Standard. A source file together with all the headers and source files included via the preprocessing directive #include is known as a preprocessing translation unit. After preprocessing, a preprocessing translation unit is called a translation unit. Previously translated translation units may be preserved individually or in libraries. The separate translation units of a program communicate by (for example) calls to functions whose identifiers have external linkage, manipulation of objects whose identifiers have external linkage, or manipulation of data files. Translation units may be separately translated and then later linked to produce an executable program.
5.1.1.2 Translation phases
All external object and function references are resolved. Library components are linked to satisfy external references to functions and objects not defined in the current translation. All such translator output is collected into a program image which contains information needed for execution in its execution environment.
The linking is done based on the names of external definitions, not on the types of the objects identified by the name. The onus is on the programmer to ensure that the type of the function or object for each external definition is consistent with the way it is used.
Avoiding the problem
In a comment, I said:
This [question] is an argument for making use of headers to ensure that different parts of a program are coherent. If you never declare an external function in a source file but only in headers, and use the headers wherever the relevant symbol (in this case weird) is used or defined, then the code would not all compile. You could either have a function or a string, but not both. You'd have a header weird.h which contains either extern char *weird; or extern int weird(int *p); (but not both), and both main.c and weird.c would include the header, and only one of them would compile successfully.
To which there came the response:
What could I add to these files to ensure that the error is detected and thrown when main.c is compiled?
You'd create 3 source files. The code shown here is slightly more complicated than you'd normally use because it allows you to use conditional compilation to compile the code with either a function or a variable as the 'external identifier with external linkage' called weird. Normally, you'd select one intended representation for weird and only allow that to be exposed.
weird.h
#ifndef WEIRD_H_INCLUDED
#define WEIRD_H_INCLUDED
#ifdef USE_WEIRD_STRING
extern const char *weird;
#else
extern int weird(int *p);
#endif
#endif /* WEIRD_H_INCLUDED */
main.c
#include <stdio.h>
#include "weird.h"
int main(void)
{
int x, *y;
y = (int *)7;
x = weird(y);
printf("x = %d\n", x);
return (0);
}
weird.c
#include "weird.h"
#ifdef USE_WEIRD_STRING
const char *weird = "weird";
#else
int weird(int *p)
{
if (p == 0)
return 42;
else
return 99;
}
#endif
Valid compilation sequences
gcc -c weird.c
gcc -c main.c
gcc -o program weird.o main.o
gcc -o program -DUSE_WEIRD_FUNCTION main.c weird.c
Both these work because the code is compiled to use the weird() function. The header, in both cases, ensures that the compilations are consistent.
Invalid compilation sequence
gcc -c -DUSE_WEIRD_STRING weird.c
gcc -c main.c
gcc -o program weird.o main.o
This is basically the same as the setup in the question. The weird.c file is compiled to create a string called weird, but the main.c code is compiled expecting to use a function weird(). The linker does link the code, but things go disastrously wrong when the function call in main() is retargeted to the "weird". The chances are that the memory where it is stored is not executable and the execution fails because of that. Otherwise, the string is interpreted as machine code and it probably doesn't do anything meaningful and leads to a crash. Neither is desirable; neither is guaranteed — this is a result of invoking undefined behaviour.
If you tried to compile main.c with -DUSE_WEIRD_STRING, the compilation would fail because the header would indicate that weird is a char * and the code would try to use it as a function.
If you replaced the conditional code in weird.c with either the string or the function (unconditionally), then:
Either the compilation would fail if the file contained the function but -DUSE_WEIRD_STRING was set on the command line,
Or the compilation would fail if the file contained the string but you did not set -DUSE_WEIRD_STRING.
Normally, the header would contain an unconditional declaration for weird, either as a function or as a pointer (but without any provision for choosing between them at compile time).
The key point is that the header is included in both source files, so unless the conditional compilation flags make a difference, the compiler can check the code in the source files for consistency with the header, and therefore the two object files stand a chance of working together. If you subvert the checking by setting the compilation flags so that the two source files see different declarations in the header, then you're back to square one.
The header, therefore, declares the interfaces, and the source files are checked to ensure that they adhere to the interface. The headers are the glue that hold the system together. Consequently, any function (or variable) that must be accessed outside its source file should be declared in a header (one header only), and that header should be used in the source file where the function (or variable) is defined, and also in every source file that references the function (or variable). You should not write extern … weird …; in a source file; such declarations belong in a header. All functions (or variables) that are not referenced outside the source file where they're defined should be defined with static. This gives you the maximum chance of spotting problems before you run the program.
You can use GCC to help you. For functions, you can insist on prototypes being in scope before a (non-static) function is referenced or defined (and before a static function is referenced — you can simply define a static function before it is referenced without a separate prototype). I use:
gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
-Wold-style-definition -Wold-style-declaration …
The -Wall and -Wextra imply some, but not all, of the other -W… options, so that isn't a minimal set. And not all versions of GCC support both the -Wold-style-… options. But together, these options ensure that functions have a full prototype declaration before the function is used.
Neither file on its own contains any error that would cause a problem with compilation. main.c correctly declares (but doesn't define) a function called weird and calls it, and weird.c correctly defines a char * named weird. After compilation, main.o contains an unresolved reference to weird and weird.o contains a definition.
Now, here's the fun part: neither .o file necessarily[*] contains anything about the type of weird. Just names and addresses. By the time linking is happening, it's too late to say "hey, main expects this to be an int(*)(int *) and what you provided is actually a char *!" All the linker does is see that the name weird is provided by one object and referenced by another, and fits the pieces together like a jigsaw puzzle. In C, it's entirely the programmer's job to make sure that all compilation units that use a given external symbol declare it with compatible types (not necessarily identical; there are intricate rules as to what are "compatible types"). If you don't, the resulting behavior is undefined and probably wrong.
[*]: actually I can think of several cases where the object files do contain the types — for example, certain kinds of debugging information, or special .o files for link-time optimization. But as far as I know, even when the type information does exist, the linker doesn't use it to warn about things like this.
I am taking a Linux point of view. Details could be different on other OSes.
Of course your latest edit cannot compile, since:
char *weird = "weird";
printf(weird); // wrong, remove this line
contains a statement (the printf) outside of any function. So let assume you have removed that line. And clang-3.7 -Wall -Wextra -c main.c gives several warnings:
main.c:7:9: warning: cast to 'int *' from smaller integer type 'int' [-Wint-to-pointer-cast]
w = (int *)x;
^
main.c:8:9: warning: cast to 'int *' from smaller integer type 'int' [-Wint-to-pointer-cast]
y = (int *)z;
^
main.c:7:16: warning: variable 'x' is uninitialized when used here [-Wuninitialized]
w = (int *)x;
^
main.c:6:10: note: initialize the variable 'x' to silence this warning
int x, *y, z, *w;
^
= 0
main.c:8:16: warning: variable 'z' is uninitialized when used here [-Wuninitialized]
y = (int *)z;
^
main.c:6:17: note: initialize the variable 'z' to silence this warning
int x, *y, z, *w;
^
= 0
4 warnings generated.
Technically, I guess that your example is some undefined behavior. Then the implementation is not supposed to warn you, and bad things can happen (or not!).
You might have some warning (but I am not sure) if you enabled link time optimization both at compile time and at link time, perhaps with
gcc -flto -Wall -Wextra -O -c main.c
gcc -flto -Wall -Wextra -O -c weird.c
gcc -flto -Wall -Wextra -O main.o weird.o -o program
and you could replace gcc by clang if you wish to. I guess that asking for optimization (-O) is relevant.
Actually I am getting no warnings with clang-3.7 -flto but I am getting a warning (at the last link command) with gcc 6:
% gcc -flto -O -Wall -Wextra weird.o main.o -o program
main.c:1:5: error: variable ‘weird’ redeclared as function
int weird(int *);
^
weird.c:3:7: note: previously declared here
char *weird = "weird";
^
lto1: fatal error: errors during merging of translation units
compilation terminated.
(I am explaining for GCC which I know well, including some of its internals; for clang it should be similar)
With -flto the compiler (e.g. lto1 with GCC) is also running for linking (so can optimize then, e.g. inlining calls between translation units). It is using compiler intermediate representations stored in object files (and these representations contain typing information). Without it, the last command (e.g. your clang main.o weird.o -o program) is simply invoking the linker ld with appropriate options (e.g. for crt0 & C standard library)
Current linkers don't keep or handle any type information (pedantically doing some type erasure, mostly done by the compiler itself). They just manage symbols (that is C identifiers) in some simple symbol table and process relocations. Lack of type information in object files (more precisely, the symbol tables known to the linker) is why name mangling is required for C++.
Read more about ELF, e.g. elf(5), the format used by object files and executables.
Replace clang or gcc by clang -v or gcc -v to understand what is happening (so it would show you the underlying cc1 or lto1 or ld processes).
As others explained, you really should share a common #include-d header file (if the C code is not machine generated but hand written). Some C code generators might avoid generating header files and would generate relevant (and identical) declarations in every generated C file.
when you want to build a executable program, you have to link object.
but now, you just compile the source.
Complier thought
"ah, you'll compile weird.c later. okay. i'll just compile this one"

without including <stdio.h>

below given program is working without including <stdio.h>? Why does this work?
int main()
{
printf("integra");
return 0;
}
Definition of printf() is there in libc.so and the dynamic linker will take care of it even if you don't include the header file. During compile time, printf() will be an undefined symbol and it assumes that it may find the definition later on in libc. The header file will just give the proto-type and suppress the compiler(warnings) stating that the definition of the prototype is present in glibc. So basically, the header files are included just to make sure that the definitions are available in our libraries, to help the developer.
in older standard, undeclared function assume int argument and return value. Your char* have same size (32-bit) as int, so everything work.
Just don't do it.
printf() is only defined in libc.so
The dynamic linker will resolve the symbol printf() in libc since you have not included it
libc is default in gcc for every program
As Abi pointed out, your code builds successfully without including stdio.h because the linker is defaulting to the system std library for the undefined symbol (printf). GCC would normally warn you of such cases.
Let test.c be:
1: int main()
2: {
3: printf("test\n");
4: return 0;
5: }
Building test.c with GCC 4.2.1 on Mac OSX:
$ gcc test.c
test.c: In function ‘main’:
test.c:3: warning: incompatible implicit declaration of built-in function ‘printf’
$ ./a.out
test
You can disable this default linking by specifying a GCC linker option -nostdlib (or -nodefaultlibs) along with -lgcc (as the GCC manual recommends):
$ gcc -nostdlib -lgcc test.c
test.c: In function ‘main’:
test.c:3: warning: incompatible implicit declaration of built-in function ‘printf’
Undefined symbols:
"_puts", referenced from:
_main in cc3bvzuM.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
$
Some (old?) compilers do not require prototypes before calling functions.
When you use a function that has not been declared, then the compiler will assume this function returns an int and takes an unspecified, but fixed, number of arguments.
If this assumption matches with the definition of the function, and if the arguments you provided also match (modulo the default argument promotions) the parameters that the function expects to receive, then everything is well.
If the assumption is incorrect (like for printf, which is a variadic function), or when the arguments don't match, the results are undefined. One of the nasty things of undefined behaviour is that it can appear to work as expected.

warning: incompatible implicit declaration of built-in function ‘xyz’

I'm getting a number of these warnings when compiling a few binaries:
warning: incompatible implicit declaration of built-in function ‘strcpy’
warning: incompatible implicit declaration of built-in function ‘strlen’
warning: incompatible implicit declaration of built-in function ‘exit’
To try to resolve this, I have added
#include <stdlib.h>
at the top of the C files associated with this warning, in addition to compiling with the following flags:
CFLAGS = -fno-builtin-exit -fno-builtin-strcat -fno-builtin-strncat -fno-builtin-strcpy -fno-builtin-strlen -fno-builtin-calloc
I am using GCC 4.1.2:
$ gcc --version
gcc (GCC) 4.1.2 20080704
What should I do to resolve these warnings?
In C, using a previously undeclared function constitutes an implicit declaration of the function. In an implicit declaration, the return type is int if I recall correctly. Now, GCC has built-in definitions for some standard functions. If an implicit declaration does not match the built-in definition, you get this warning.
To fix the problem, you have to declare the functions before using them; normally you do this by including the appropriate header. I recommend not to use the -fno-builtin-* flags if possible.
Instead of stdlib.h, you should try:
#include <string.h>
That's where strcpy and strncpy are defined, at least according to the strcpy(2) man page.
The exit function is defined in stdlib.h, though, so I don't know what's going on there.
In the case of some programs, these errors are normal and should not be fixed.
I get these error messages when compiling the program phrap (for example). This program happens to contain code that modifies or replaces some built in functions, and when I include the appropriate header files to fix the warnings, GCC instead generates a bunch of errors. So fixing the warnings effectively breaks the build.
If you got the source as part of a distribution that should compile normally, the errors might be normal. Consult the documentation to be sure.
Here is some C code that produces the above mentioned error:
int main(int argc, char **argv) {
exit(1);
}
Compiled like this on Fedora 17 Linux 64 bit with gcc:
el#defiant ~/foo2 $ gcc -o n n2.c
n2.c: In function ‘main’:
n2.c:2:3: warning: incompatible implicit declaration of built-in
function ‘exit’ [enabled by default]
el#defiant ~/foo2 $ ./n
el#defiant ~/foo2 $
To make the warning go away, add this declaration to the top of the file:
#include <stdlib.h>
I met these warnings on mempcpy function. Man page says this function is a GNU extension and synopsis shows:
#define _GNU_SOURCE
#include <string.h>
When #define is added to my source before the #include, declarations for the GNU extensions are made visible and warnings disappear.

Resources