Why is it not good practice to include source files into other source files? Better way is to include header files instead. What are the benefits from such approach and what are the drawbacks from the vice versa? Excuse my bad English.
-
3No point in doing that. The compiler takes each source file in the project as an **independent compilation unit**. Once it finishes compiling a given unit, it "forgets" all the previous definitions (macros, function prototypes, etc). If you include a source file in a source file, the former will be compiled twice, and all the global symbols in it (functions and global variables) will be instantiated twice, leading to linkage errors. – barak manos Jun 23 '15 at 12:07
-
You _do_ `#include` source code files! Although not exacty fitting, [here](http://stackoverflow.com/questions/30873206/header-file-included-only-once-in-entire-program/30873377#30873377) you might find an explanation why having _definitions_ in a header is bad practice (with some exceptions). – too honest for this site Jun 23 '15 at 12:09
-
1@barakmanos: Confusing "source code file" and "input file"? Note that the standard refers to "file scope", meaning the whole compilation unit, including any `#include`d files. Note also, there _are_ actually good use-cases where you include _definitions_: for instance, automatically generated tables you want to keep `static`. Or - even for normal headers: `inline` functions. – too honest for this site Jun 23 '15 at 12:10
-
@Olaf: I agree about the auto-generated (typically large) arrays, but since it is not the common case, I have assumed that OP is referring to the "normal" development process, where you "manually" create and add your code in one or more source files. – barak manos Jun 23 '15 at 12:50
-
@barakmanos: What is a "normal development process"? By that you discriminate the large field of embedded systems, where such includes are pretty common, as much as other static definitions in headers (often using special sections of the code). – too honest for this site Jun 23 '15 at 12:53
-
1@Olaf: BTW, for those auto-generated tables, you can use `extern` instead of including the source file. – barak manos Jun 23 '15 at 12:54
-
@barakmanos: read my answer. The are often good reason to have them `static`. Remember C does not have user-defined namespaces, so every `extern` pollutes the program's namespace. – too honest for this site Jun 23 '15 at 12:55
-
1@Olaf: If you declare the auto-generated table `static` and include the source file in several places, then you create several copies of that table. This might prove quite wasteful, in particular in embedded systems which you've just mentioned. – barak manos Jun 23 '15 at 13:06
-
@barakmanos: Please do not add implications I did not state. Read my answer, I am not up to discuss this multiple times. And there are other cases to have a `static` struct being included in multiple files from a header, but with different data and in a special section as I stated, however, _this one_ is a less common usage, I very well admit. – too honest for this site Jun 23 '15 at 13:18
5 Answers
As mentioned before, the main argument against including C files into C files, is the high risk of multiple definition errors. And since it is a very seldom used technique, it causes unexpected side effects for code maintainers.
Of course, in very special cases, including a C-File might be the lesser of two evils. For example, if you want to write unit tests for static c functions, you might include the C file into the file with the unit test.
see also: How to test a static function
Another unusual but valid use is separating class or function templates from their definition (C++): https://isocpp.org/wiki/faq/templates#separate-template-fn-defn-from-decl
Why is it not good practice to include source files into other source files?
Source files contain definitions. These can cause multiple definition errors and thus generally should not be included in other source files. Even if you avoid multiple definition error by compiling only the files which includes other source file, code can become unmanageable.
In header files, you just introduce some symbols to compiler and inform their types. This allows you to separate the interface with the implementation.
For example:
file a.c
int a = 42;
...
file b.c
/* Example of bad code */
#include "a.c"
...
When you compile a.c
and b.c
and link them you will get multiple definition
linker error.
If one plans to include multiple source files into just one file and compile that one file, it will introduce a lot of pollution (macros, static functions etc) which is something not very manageable for readers and for the compilers.
p.s. When I say generally, I mean sometimes including source code may be useful. But in such cases to avoid the confusions to readers, I would prefer to rename the file suffix to some thing other than .c
, may be .inc
or similar.

- 30,259
- 8
- 73
- 100
-
1Header files should also be guarded with `#ifndef...#endif` so if there are symbols defined in them they will not produce linker error if included in multiple files. Declaring symbols in header files is sometimes useful, although should be avoided. The file extension is only an information for the developer, there is no need for .h extension, very well known example are files like 'iostream' which have no extension. – riodoro1 Jun 23 '15 at 12:13
-
2@riodoro1 defining **symbols** in header files is not a good idea, and the include guard is not for that, it's to prevent including the same file twice, defining a `struct` for example will be a problem if you include the file twice. – Iharob Al Asimi Jun 23 '15 at 12:15
-
@riodoro1 No they will still cause multiple definition error because compilation units are completely isolated with each other while compilation. – Mohit Jain Jun 23 '15 at 12:15
-
To a preprocessor, the extension of a file really doesn't matter. You could put code into a file with a "JPG" extension and you could still #include it without error provided that the code is legit.
One of the reasons why, conventionally, it's considered bad practice to #include
files with a source file extension is from a basic build/make perspective. Imagine you are porting a large-scale project to a new, cross-platform build system (say, 50 million lines of code).
You now have to specify which files are to be built as separate compilation units (object files) to be compiled separately and linked to form the resulting binary. If your codebase has a habit of using the preprocessor to include files with a source file extension, then you have no idea just looking at the file extensions which files are to be build as separate compilation units and which files are actually just meant to be included by the preprocessor. So then you might face a spam of errors just trying to build all the source files as separate compilation units as a sane person would, and may have to debug your build process using a fine-tooth comb while inspecting all your code and trying to figure out which file is meant for what.
At a higher level, beyond file extensions, if you actually define things in source files and include them with the preprocessor, then you risk redundant linker definitions of the same symbols, tricky link-time (and possibly compile-time) errors. Moreover, this can exhibit a general breakdown in thinking between the separation of interface/declaration (headers) and implementation/definition (sources).
There are exceptions like unity builds which do this as a build-time optimization and may be somewhat acceptable with careful coding standards and with real, measured benefits to the practice, but in general, including source files can be really confusing and a sign that the developer doesn't really understand the point of separating declarations from definitions or the confusion this can cause when trying to establish a build system.
The c source files must have definitions, for example if you have a function int add(int, int)
that adds two numbers, then a definition of it would look like
int add(int x, int y)
{
return x + y;
}
a header file, contains a prototype that helps the compiler call this function when it's called in your code, it tells the compiler how to create the stack frame for the function, how many parameters and their types, and the return type.
If you include a c source file containing the code sample from above, then two definitions of the function add()
will be needed, which is not possible.
Instead you add the prototype to a header file, like this
int add(int x, int y);
and then include the header file, this way there will be a single definition for the add()
function.
You might be asking yourself then, how will the function work if I use it in another c source file without providing a definition?
The answer is that the function definition is only required when the compiler links all the object files into the final binary.

- 52,653
- 6
- 59
- 97
-
I always wonder why people forget about `inline` functions or automatically generated `static` tables. You do not want to add them every time to your _implementation file_. – too honest for this site Jun 23 '15 at 12:14
Any file #include
d is compiled as if its text does replace the corresponding #include
directive by the preprocessor. Although not exacty fitting, here you might find further information about this here. Note the preprocessor-guard.
The actual question is, what you should not put into such a header. That would be everythink which makes a names with external linkage be defined in more than one compilation unit/module. You also should not put objects here, which are used in only one such module, and/or shall be hidden from other modules.
That would include functions in general: the header only provides the declaration, the definition will be in a single module. An exception are inline
functions, which actually have to be defined in the header.
For data structures, most times, the same applies as for functions. However, there might be exceptions for static
structures which have to be provided by all modules. Another exception might be automatically generated files, e.g. tables which are only used by a single module. These should also be #include
d, but declared static
. Normally, one would use a different extension for such files, e.g. .inc
instead of .h
.

- 1
- 1

- 12,050
- 4
- 30
- 52