In order to use particular functions we must include a header file. However in the header file all it has are lines like "int __cdecl printf(const char *,...);". I understand that that line declares the function "printf", but where is the actual code for printf? Is it all in the compiler to begin with? Does a header file work if it didn't come with the compiler?
Thank you for your time,
No, the compiler does not contain the code for printf that you would call from you're own program.
Such code, being part of the C and C++ standard libraries is generally distributed in the form of libraries.
A library, in this sense, is a collection of compiled code. They come in two types: static and dynamic (or shared).
A static library is really just a collection of compiled source code. That is it is a collection of object code (remember object code files are the output from successful compilations). Separate tools (programs) are used to create and manage such libraries. The standard UNIX/Linux tool is called ar - short for archiver and the Microsoft tool is called lib (for librarian). It is a convenience as a single library file can consist of object code from a great many object files which would otherwise be very cumbersome to make use of by many people (one of the main use cases for libraries is that they can be distributed to and used by many people - as is the case with the C/C++ library files that are distributed with C/C++ compilers).
Before the output from the compiler (the object code file) can be used in an executable it, together with any other object files that result from compiling other parts of a program, and any libraries that they use the facilities of - such as the C/C++ library containing the code for printf - have to be linked together. This stage is called linking.
So the general model is that first all the parts of a program are compiled, some parts may be packaged as libraries, and then they are linked together to form executables. Note that the compilation does not have to all happen at the same time or on the same machine. For example returning to the case of C/C++ libraries shipped with a pre-built set of development tools (compiler, linker, librarian etc.) the source code for the libraries would have been compiled to object files which were then packaged into libraries for distribution which were then obtained and installed by people like us. We would then compile our own source files and link them together with the pre-built C/C++ library.
Dynamic link libraries (DLLs - as used by Microsoft Windows and other systems) or shared object libraries (.so files, as used by UNIX, Linux and similar/related systems) are loaded into process memory like program executables. Unlike static libraries but like program executables they have to be fully linked before they can be used. Depending on the exact variety of dynamic/shared library you either link with them directly or link with a separate static library containing stub code to the dynamic library's facilities (called an import library or implib by Microsoft development tools and documentation).
With static libraries each executable (or dynamic/shared library) that they are linked into contains a copy of the code used by that program/library, which will then be loaded into the process memory along with the rest of the program/dynamic-library code when it is loaded to be executed.
With dynamic/shared libraries the code is left in the dynamic/shared library file and only a stub is placed in the program/dynamic library using its features. When a program starts any dynamic libraries are also mapped into the process address space so that its features can be used. If one dynamic/shared library refers to another then when one is loaded into a process so must the other be. Due to the wonders of virtual memory a single image (loaded data of) a dynamic/shared library can be shared among many different processes (hence the term shared object library).
The terms static and dynamic here refer to the point at which the code is made available, as it were, to a program (or dynamic/shared library). Code in a static library is made available at build time (i.e. it is statically built into the executable file). A dynamic library is made available dynamically at runtime. Operating systems that support dynamic/shared libraries usually provide facilities to explicitly load and access the functions of dynamic/shared libraries within your own programs or libraries. Note also that these facilities are non-standard C and C++ and operating system specific.
As the code for the facilities of any statically linked libraries ends up in the program or dynamic/shared library executable file - it will get distributed when this file is distributed. However, if a program (or dynamic/shared library) uses any dynamic/shared libraries then the files for these libraries _must_ also be available, accessible and locatable on each system the program or dynamic/shared library file is installed on for it to be usable.
As to your query regarding header files. A header file is merely textually included source code and is a simple method to share code such as function/data declarations and type definitions and aliases between parts of a program (or library) and between programs/libraries to ensure such things are consistent. Hence a header file will 'work' if it is used with any compatible compiler. As the only thing source code for languages such as C and C++ is ultimately used for is to be compiled by a compiler it is not clear how one could 'work' without one. As they are text and human readable I suppose they could be said to work if they convey something to human readers (making maintenance easy for example)...
Note that in the previous paragraph I said "compatible compiler". This is because declarations in header files for libraries provided with a specific compiler can make use of non-standard, compiler specific extensions, such as the Microsoft compiler specific __cdecl. Note the double underscore prefix, which indicates it is a language or library extension and is non-standard. Using non-standard features will of course restrict the compilers header files, and implementation source files, will 'work' with, although using various configuration methods (e.g. conditional compilation preprocessor directives such as #ifdef) can allow such uses based on the compiler in use at the time.
Most header files do not come with a compiler. They may be those for your own projects, or projects for organisations or people you work with or for or be the header files supplied with some third party library (of which there are a great many) or operating system (e.g. the Microsoft platform SDK).
So to sum up, with C and C++ you generally require two types of things to make use of a library: a set of header files that declare and define the objects (in the sense of functions, types, global data etc.) of the library so you can make use of them at the source code / compilation stage and one or more library files that is / are used at the link stage to inject the actual code.
I should note that with the popularity of the use of templates in C++, in which all the code is always included, we are seeing many more of what are sometimes called header only libraries. That is they consist only of header files and no library files need to be built and linked with to use them. See the Boost (http://www.boost.org/
) libraries (http://www.boost.org/doc/libs/1_37_0
) for some examples of header only libraries (note that not all Boost libraries are header only).
Hope this has been helpful to you. If there are some things you did not understand (maybe because I did not explain them very well), or you have further queries then please post further questions (possibly a follow up if it is related to this question and/or answer).