Reputation:
For example:
#include <stdio.h>
//#include <stdio.c> stdio.c is not needed but why?
int main()
{
printf("Hello World");
return 0;
}
To use printf
and make the program compile, we add #include <stdio.h>
. But we know that .h
is just header files and real definition of printf
is in stdio.c
, so why we don't need to include it like the header as #include <stdio.c>
? and how does the linker even produce executable object file without the essential stdio.c
being included?
Upvotes: 3
Views: 1939
Reputation: 2275
Technically, there is nothing stopping you from #including
a source file. The include directive simply copy-pastes the contents of the included file into the including file before the next compilation step. If you were to #include
a C file, it would still do the same thing. But then, if you wanted all your code in one translation unit, you wouldn't have split them up into multiple files in the first place. That we #include
only header files and not C files is more of a convention than something that the language mandates. Rarely, you can see code out there that #includes
C files to handle some special cases.
Coming to the second part of your question, the contents of what you call 'stdio.c' is available already, shipped with your compiler in binary form as the C standard library. The linker implicitly links with the standard library even though you do not specify this when compiling and linking your code.
Upvotes: 5
Reputation: 1
The linker does not care about any #include
's you make. It links the libraries you tell it should link to, normally given as command line arguments.
On Linux, not sure about Windows or Mac, you can test this by using a function from math.h
. The math functions are usually in libm.so
while the other functions of the C-standard are in libc.so
. libc.so
is linked per default, libm.so
is not linked per default. That is why you normally need to add the -lm
flag to GCC when you use math functions.
#include <math.h>
int main(void)
{
//use volatile so GCC does not optimize exp() out
volatile double v=3;
return exp(v);
}
If you try to compile and link it with gcc ./main.c -o test
you get an error, you need to add the -lm
flag. After linking you can check the used shared libraries with readelf -d test | grep lib
and you see that the program needs libm.so
or libm.so.6
and libc.so
or libc.so.6
. If you run the program, the libraries will be loaded and used. The definitions of the linked objects are not included in your program when you use dynamic linking (default for libraries).
Upvotes: 2
Reputation: 123448
how does the linker even produce executable object file without the essential
stdio.c
being included?
The standard library functions have already been compiled into one or more libraries stored in a well-known location, and those are automatically linked by the compiler.
There are several practical reasons why we typically do not #include
source files into each other:
#include "C.c"
#include "B.c"
#include "A.c"
then you'll get an error that the functions in module C are missing stuff from module A. If you write
#include "A.c"
#include "C.c"
#include "B.c"
then the dependency of C on A is resolved, but now A doesn't have the definitions from B that it requires.
Splitting declarations off into separate .h
files helps resolve this problem.
Breaking code up into independently compiled modules also makes testing easier, it makes code reuse easier, it makes upgrades easier, etc.
Upvotes: 1
Reputation: 3691
I've come across several projects which actually do #include
source files, usually this is to squeeze every last drop of performance to avoid some extra jumps or allowing the compiler to optimize/inline functions, or to do some preprocessor trickery on the "included" source file.
Generally speaking, however, header files contain symbol declarations and structure definitions which may inform the compiler about how functions are to be called and how structure members are arranged in memory.
The actual definition of symbols, as other have mentioned, resides in other objects and are resolved by the linker.
It's important to note that the dynamic linker has two main functions:
That being said, the source code of printf
is not required until the application is actually launched.
Upvotes: 2