TL / DR: Your compiler / linker is finding the dependencies you've included (e.g. stdlib.h
) in some library in the default path. Depending on the build / link options, the library is being dynamically or statically included.
Your question has a simple answer, but it is not possible to talk about what happens without reviewing a series of concepts:
Dynamic vs. Static Libraries
C / C ++ libraries can be linked statically or dynamically.
In a gross simplification, static linking produces an independent executable with a copy of the library; that is, you end up with a larger executable containing the binary of your application and the library. If you need to change the library you will need to recompile your application to include the new changes.
In contrast, dynamic linking produces independent artifacts. A shared library (usually .so
on * NIX systems and .dll
on Windows) is loaded in load time or run time . Roughly the application that references a dynamic library contains a "symbol table" indicating external dependencies, when any of these dependencies (eg, any function) is requested it is "loaded into memory" (the details of the "algorithm" that determines how e which library should be "loaded" are complex, I do not want to get into that merit).
The advantage of dynamic libraries is that a single library can be shared among multiple executables; Additionally, libraries can also be updated independently (as long as binary compatibility is maintained). The disadvantage is that complex projects can wipe out a deep graph of dependencies, creating all sorts of problems (version incompatibility, accidental inclusion of legacy versions of the library, need to backport / em> security for legacy versions, etc, etc, etc).
Templates
In addition to function prototypes, structs, classes, and enumerations (part of a library's "signature / interface"), templates are included in the headers. At compile / link time, specific versions of the parameterized constructs are generated (e.g., a version with int
and another with float
of a function template) embedded in the application binary. That's why in some compilers the size of the binary grows significantly when you use, for example, std .
How the linker finds a library
How does your link find a library? Roughly it does a search on the path (path) where libraries are made available. @pmg's answer mentions libc
; the linker can find an implementation such as libc.so
or msvcrt.lib
in an infinite number of places by an infinite number of rules (flags passed to the linker, environment variables such as LD_LIBRARY_PATH
, default directories as /usr/lib
, current directory application, etc, etc, etc). The rules often vary with the operating system and build stack.
So what happens when I include libraries like stdlib.h
, iostream
, etc?
In sufficiently complex applications, the required libraries are located and a combination of dynamic and static linking occurs, as well as template instantiation / expansion.
While most compilers will by default make it possible to link libraries dynamically, a portion of the library code ends up being directly or indirectly copied / expanded within the executable.
Contenders are often able to report everything that has been linked statically and dynamically (e.g., gcc -Wl --verbose
). Additionally, tools like ldd
and Dependency Walker can list dependencies.