Skip to content

Chapter 7 of 7

Compilation, Linking, and Program Structure

A C program is built in four stages. The preprocessor resolves directives, expands macros, and includes headers to produce a translation unit. The compiler parses that unit, performs type checking, and emits assembly code. The assembler converts assembly into relocatable object code in .o files. Finally, the linker combines object files and libraries, resolves external symbols, and produces an executable. The compiler handles one source file at a time, while the linker ties multiple files together. This separation is why declarations and definitions are distinct: extern int counter; declares a variable that exists elsewhere, while int counter = 0; actually allocates storage, and multiple definitions of the same symbol cause a linker error.

Linkage governs whether a symbol is visible across translation units. By default, non-static globals and functions have external linkage and are visible everywhere; applying static at file scope gives internal linkage, hiding the symbol within its own source file. Inside functions, static means the local variable retains its value across calls. Header files with a .h suffix contain declarations that provide an interface, so other source files can use features without seeing the implementation. Each .c file is compiled independently, and the linker matches each declaration to its single definition, errors on undefined or multiply-defined symbols, and produces the executable. The C standard itself has evolved through versions including C89, C99, C11, C17, and C23, with each adding features such as fixed-width integers, designated initializers, threads, atomics, and refined attribute syntax; C and C++ also remain distinct languages with different rules for constructs like character literals.

Libraries come in two forms. A static library, with .a on Unix and .lib on Windows, is a bundle of object files copied into the executable at build time, producing a self-contained binary that does not depend on the library at runtime. A shared library, with .so on Linux, .dylib on macOS, and .dll on Windows, is loaded by the dynamic linker at runtime and shared between processes, yielding smaller binaries and easier patching at the cost of runtime symbol resolution. Storage durations in C are automatic (block scope), static (program duration), allocated (malloc through free), and thread (_Thread_local, one copy per thread). A typical process address space is divided into read-only text, initialized data, zero-initialized BSS, the heap (which grows up through malloc), and the stack (which grows down with each function call). The main function has two standard signatures, int main(void) and int main(int argc, char *argv[]), where argc is the argument count and argv is an array of argument strings terminated by a NULL pointer; the value returned from main becomes the process exit status. Low-level helpers like offsetof, which returns a struct member's byte offset, and the container_of pattern, which recovers a containing struct from a pointer to an embedded member, rely on these layout guarantees and are widely used in systems code.

All chapters
  1. 1Pointers and Dynamic Memory
  2. 2Data Types, Variables, and User-Defined Aggregates
  3. 3Arrays, Strings, and Memory Operations
  4. 4Functions and Control Flow
  5. 5File I/O and Program Termination
  6. 6The Preprocessor and Macros
  7. 7Compilation, Linking, and Program Structure

Drill it

Reading is not remembering. These come from the C Programming deck:

Q

What is a pointer in C?

A pointer is a variable that stores the memory address of another variable.Declared using the * operator: int *ptr;The address-of operator & retrieves a var...

Q

How do you dereference a pointer?

Dereferencing means accessing the value stored at the address a pointer holds.Use the * operator: int val = *ptr;This retrieves the value at the memory location...

Q

What is a NULL pointer?

A NULL pointer is a pointer that does not point to any valid memory location.Assigned with: int *ptr = NULL;Always check for NULL before dereferencing to avoid...

Q

What does malloc() do in C?

malloc() allocates a block of memory on the heap and returns a pointer to it.Syntax: int *p = (int *)malloc(n * sizeof(int));Returns NULL if allocation fails. M...