15

If I #include a file in C, do I get the entire contents of the file linked in, or just the parts I use?

If it has 10 functions in it, and I only use one of the functions, does the code for the other nine functions get included in my executable? This is especially relevant for me right now as I am working on a microcontroller and memory is precious.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • 4
    Possible duplicate of [Do unused functions get optimized out?](http://stackoverflow.com/q/6215782/69809) or [Do compilers remove unused functions, definitions, variables, macros, includes etc?](http://stackoverflow.com/questions/6215782/do-unused-functions-get-optimized-out) – vgru Feb 18 '16 at 00:23
  • 1
    You might want to check some existing threads ([Do unused functions get optimized out?](http://stackoverflow.com/q/6215782/69809), [Do compilers remove unused functions, definitions, variables, macros, includes etc](http://stackoverflow.com/q/15782515/69809)). It depends on the compiler, but often non-static functions don't get optimized because it's only in the linker phase that the build process knows whether a function will actually be used. But such functions are rare in header files, as @nneonneo already wrote. – vgru Feb 18 '16 at 00:25
  • 1
    #including a file has literally the same effect as copy-pasting it. – user253751 Feb 18 '16 at 00:33
  • @user253751: What about [precompiled headers](https://stackoverflow.com/questions/4726155/what-is-stdafx-h-used-for-in-visual-studio/4726838#4726838)? – Peter Mortensen Sep 03 '22 at 09:53
  • @PeterMortensen That is copy-paste with caching. – user253751 Sep 03 '22 at 14:26

4 Answers4

20

Firstly, header files do not get "linked in". #include is basically a textual copy-paste feature. Everything from your include file gets pasted by preprocessor into the final translation unit, which will later be seamlessly processed by the compiler proper. The compiler proper knows nothing about any header files or #include directives.

Secondly, it means that if in your code you declared or defined some function or variable that you do not use, it is completely irrelevant whether it came from a header file through #include or was written directly in source file. There's absolutely no difference.

Thirdly, the question is: what exactly do you have in your header file that you include? Typically, header files do not define objects and functions, they simply declare them. Declarations do not produce any code, regardless whether you use the function or not. Declarations simply tell the compiler that the code (generated from the function definition) already exists elsewhere. Thus, as long as we are talking about typical header files, #include directives and header files by themselves have no effect on final code size.

Fourthly, if your header file is of some unusual kind that contains function (or object) definitions, then see "firstly" and "secondly" above. The compiler proper can see only one translation unit at a time, for which reason a typical strategy for the compiler proper is to completely discard unused entities with internal linkage (i.e. static objects and functions) and keep all entities with external linkage. Entities with external linkage cannot be discarded by compiler proper, since they might be needed in some other translation unit.

Fifthly, at linking stage linker can see the program in its entirety and, for that reason, can discard unused objects and functions, if it is advanced enough for that (and if you allow linker to do it). Meanwhile, inclusion-exclusion precision of a typical run-of-the-mill linker is limited to a single object file. Each object file is atomic to such linker. This means that if you want to be able to exclude unused functions on per-function basis, you might have to adopt "one function per object file" strategy, i.e. write one and only one function per .c file. Of course, this is only possible when you write your own code. If some third-party library you want to use does not adhere to this convention, then you might not be able to exclude individual functions.

Jeffrey Bosboom
  • 13,313
  • 16
  • 79
  • 92
AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
10

If you #include a file in C, the entire contents of that file are added to your source file and compiled by your compiler. A header file, though, usually only has declarations of functions and no definitions (so no actual code is compiled).

The linker, on the other hand, takes all the functions from all the libraries and compiled source code and merges them into the final output file. At this time, the linker will discard any functions that you aren't using.

So, to answer your question: only the functions you use (and indirectly depend on) will be included in your final program file, and this is independent of what files you #include. Happy hacking!

nneonneo
  • 171,345
  • 36
  • 312
  • 383
  • 1
    "At this time, the linker will discard any functions that you aren't using." The other answers explain that this is not exactly true - more often, the linker will discard any *object files* you are not using. – Nate Eldredge Feb 18 '16 at 05:49
  • 1
    If it's a static archive, the linker only takes the object files that it needs from the library and includes them in the executable. If it's a shared library, it arranges to load the whole library at run time, but doesn't include anything except the reference information in the executable. I'd rephrase the opening sentence of the second paragraph to something like: _The linker, on the other hand, takes all the functions from the compiled source code (object files) and what's necessary from the libraries and merges them into the final output file (usually an executable)._ – Jonathan Leffler Feb 18 '16 at 15:35
1

You have to distinguish between different scenarios:

  1. What does the included header file contain? Declarations of external functions only, or also static function definitions?
  2. How are the implementations of the external functions distributed which are declared in that the header file you include? Are they all implemented in one .c file, or distributed across several .c files?

Regarding point 1: Only by #includeing external declarations, no other code will become part of your object file. And, definitions of static functions that are part of the header file, but which are not referenced by your code, may not become part of your object file - this is an optimization that is fairly common. It depends on your compiler, however.

Regarding point 2: Some linkers can only link whole object files, all or nothing. That means, if all the external functions declared in a header file are implemented in one .c file, and, if your code references at least one of these functions, chances are that you will get the whole object file, including all the other functions you don't use. Some linkers, however, can avoid this and remove unused parts when linking object files.

One brute-force approach to deal with non-optimizing linkers is, to put every external function into a .c file of its own. You will, however, have to find a way to deal with the situation that some of these functions refer to a common static function that is part of the original .c file...

Dirk Herrmann
  • 5,550
  • 1
  • 21
  • 47
0

Include simply presents the compiler ultimately with what looks like a single file (and if you do save-temps on GCC you will see that exactly a single file is presented to the actual compiler). It is no more complicated than that. So if you have some function prototypes or defines in your .c file then having them come from an include makes no difference whatsoever; the end result is the same.

If the things you include include code, functions, and not just prototypes, then it is the same as if you had those in the .c file itself. Whether or not those show up in the final binary has to do with whether or not you declared them as global or not using static, and then whether or not you optimized, etc. The same goes for variables and structures and other things.

Not all linkers are the same, but a common way to do it is whatever the compiler left in the object goes into the final binary. But if you take those objects and make a library out of them then some/many(?) linkers don’t suck everything into the binary on the portions that are required to resolve the dependencies.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
old_timer
  • 69,149
  • 8
  • 89
  • 168