C Header Files and Several Files
Real programs are too big for one file. C lets you split a program into several .c files, each with a clear job, and share what they offer through header files (.h).
The pieces
A typical split for a small geometry library looks like this:
geometry.hdeclares what the library offers: function prototypes, types and constants.geometry.cdefines those functions.main.cincludesgeometry.hand uses the functions.
/* geometry.h */
#ifndef GEOMETRY_H
#define GEOMETRY_H
double circleArea(double r);
double rectangleArea(double w, double h);
#endif/* geometry.c */
#include "geometry.h"
#define PI 3.14159265358979
double circleArea(double r) {
return PI * r * r;
}
double rectangleArea(double w, double h) {
return w * h;
}/* main.c */
#include <stdio.h>
#include "geometry.h"
int main(void) {
printf("circle: %.2f\n", circleArea(2));
printf("rectangle: %.2f\n", rectangleArea(3, 4));
return 0;
}Try it in the editor opens all three files in one folder. They are compiled together: every .c file must be on the command line (or use *.c, which is what Run does), and the header is found through #include. In the terminal you can type the command yourself:
gcc -Wall main.c geometry.c -o main && ./main
circle: 12.57 rectangle: 12.00
The Run button compiles all the .c files in the folder of the open file, so it works too.
Include guards
The lines #ifndef GEOMETRY_H, #define GEOMETRY_H and #endif are an include guard. If a header is included twice, for example by two other headers, the second copy is skipped, and the compiler does not complain about things declared twice. Every header should have one. Many compilers also accept the shorter #pragma once.
What goes where
- Header: prototypes,
typedefandstructdefinitions,#defineconstants,externdeclarations of shared variables. No function bodies, no variable definitions. - Source file: function definitions, and variables. Helpers that other files should not use are marked
static, which keeps them private to that file.
How the build works
Each .c file is compiled on its own into an object file. The linker then joins the object files into one program and connects each call to its function. A forgotten .c file on the command line shows up as a linker error such as undefined symbol: circleArea: the prototype was there, but the body was not.
Practice exercises
- Create the geometry files in the editor and build the program with the command above.
- Add
double triangleArea(double base, double height)to the header and the source file, and use it frommain. - Leave
geometry.cout of the command and read the linker error. - Add a
statichelper function togeometry.cand try to call it frommain.c.