Multi-File Compilation
Header guards, declarations vs definitions, separate compilation.
How a project made of several .c files actually becomes one program, and the guard that stops a header from breaking everything if it gets included twice.
/* point.h */
#ifndef POINT_H
#define POINT_H
struct point { int x, y; };
struct point make_point(int x, int y); /* declaration only */
#endif
/* point.c */
#include "point.h"
struct point make_point(int x, int y) { /* the actual definition */
struct point p = {x, y};
return p;
}A declaration just tells the compiler a function or type exists somewhere; a definition is the actual body. Headers hold declarations so multiple .c files can share them; each .c file gets compiled to its own .o separately, and the linker stitches the .o files together afterward, matching each call to wherever the real definition lives.
The #ifndef/#define/#endif guard exists because a header can get #included indirectly more than once in the same translation unit — without it, the second inclusion redefines struct point and the compiler rightly refuses.
Notes from readers
Comments — via GitHub