Static & Dynamic Linking
Once code is compiled into object files, it's often packaged into a library so it can be reused across multiple programs without recompiling it every time. C supports two fundamentally different kinds of libraries — static and dynamic (shared) — and understanding the trade-off between them matters for binary size, startup time, and how you ship updates.
Static Libraries
A static library (a .a file on Linux/macOS, .lib on Windows) is essentially a bundle of pre-compiled .o object files. When you link a program against a static library, the linker copies the needed code directly into your final executable. The result is a single, self-contained binary with no external dependency on that library at runtime.
# Create a static library from object files gcc -c mathutils.c -o mathutils.o ar rcs libmathutils.a mathutils.o # Link a program against it statically gcc main.c -L. -lmathutils -o program
Dynamic (Shared) Libraries
A dynamic or shared library (.so on Linux, .dylib on macOS, .dll on Windows) is not copied into the executable. Instead, the executable just records that it needs the library, and the operating system loads it into memory at runtime, when the program starts (or even later, if loaded on demand).
# Create a shared library (position-independent code is required) gcc -c -fPIC mathutils.c -o mathutils.o gcc -shared mathutils.o -o libmathutils.so # Link a program against it dynamically gcc main.c -L. -lmathutils -o program # At runtime, the OS needs to find libmathutils.so, e.g.: export LD_LIBRARY_PATH=. ./program
Static vs Dynamic: A Comparison
Aspect | Static linking | Dynamic linking |
|---|---|---|
Binary size | Larger (library code is embedded) | Smaller (library stays external) |
Startup time | Slightly faster (no library loading step) | Slightly slower (OS must locate/load the library) |
Updating the library | Requires recompiling/relinking the executable | Replace the shared library file; the program picks it up automatically |
Memory sharing | Each process gets its own copy of the code | Multiple processes can share one in-memory copy of the library |
Deployment | Single self-contained binary, easy to distribute | Must ensure the correct shared library version is present on the target system |
Choosing Between Them
Static linking is attractive when you want a single, portable binary with no external dependencies — common for command-line tools you hand out to people who may not have the right libraries installed.
Dynamic linking is attractive when many programs on a system share the same library (like the C standard library itself) — it saves disk space and memory, and lets you patch a security bug in the library without recompiling every program that uses it.
Most operating systems dynamically link the C standard library by default, even for programs you compile yourself, unless you explicitly request a fully static build.
Forcing a Fully Static Build
gcc main.c -static -o program