I have three files, test.c, foo.c, foo.h.
In foo.c i
#include "foo.h"
In test.c i
#include "foo.c."
Then when I compile my code, I use gcc -o test test.c, and it compiles.
However, my professor told me, I should use
#include "foo.h"
inside my test.c rather than #include foo.c
, and I should compile it this way
gcc -o test test.c foo.c
Is the second way more preferred? If it is, why? What's the difference between these two compilation?
In most cases you should never include source files (apart from cases where you would probably want to include a piece of code generated dynamically by a separate script). Source files are to be passed directly to the compiler. Only header files should be included.
Although the way that your professor suggests is correct, the following way has more educational value in this case:
gcc -c test.c
gcc -c foo.c
gcc -o test foo.o test.o
The first two lines compile each source file to an object file, and the third line doesn't really compile but only invokes the linker to produce an executable out of the 2 object files. The idea is to make a distinction between compiling and linking, which would be performed transparently in the way your professor suggests.
The major reasons not to #include
.c files in other .c files are:
Avoid duplicate definition errors: suppose foo.c
defines the function foo()
. You have two other files that use foo()
, so you #include "foo.c"
in both of them. When you try to build your project, the compiler will translate foo.c
multiple times, meaning it will see multiple attempts to define the foo
function, which will cause it to issue a diagnostic and halt.
Minimize build times: even if you don't introduce duplicate definition errors, you wind up recompiling the same code needlessly. Suppose you #include "foo.c"
in bar.c
, and you discover you need to make a one-line change in bar.c
. When you rebuild, you wind up re-translating the contents of foo.c
unnecessarily.
C allows you to compile your source files separately of each other, and then link the resulting object files together to build your applications or libraries. Ideally, header files should only contain non-defining object declarations, function prototype declarations, type definitions, and macro definitions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With