C Headers, Prototypes and Separate Modules
C Headers, Prototypes and Separate Modules
Two school programs need the same mark-total function. A declaration can describe how to call it, while one separately compiled source file supplies its definition.
A header normally exposes declarations and types shared by source files. A function declaration describes its contract; one corresponding definition supplies its body for linking.
Explain
Distinguish a callable declaration from a function definition and plan separate compilation.
Trace
Reuse the declared helper for 45 and 38.
Apply
Compile and link the files that supply a declared function.
Headers and Modules: follow the data
Start
Two school programs need the same mark-total function. A declaration can describe how to call it, while one separately compiled source file supplies its definition.
Operation
A header normally exposes declarations and types shared by source files. A function declaration describes its contract; one corresponding definition supplies its body for linking.
Result
Total: 75
Understand the operation
The declaration lets the compiler check arguments and result type before a call. In a multi-file project, a marks.h header could declare int total(int, int), marks.c could define it, and main.c could include the header. Compile and link both source files.
Use an include guard in a repeatedly included header. Do not place ordinary externally linked function definitions or mutable global definitions into a header included by several files. The complete example keeps a declaration and definition in one file for a directly runnable first step.
Read the complete C program
This complete C17 program uses a small school example. Read declarations before the statements that use their values. Each printf format describes how the corresponding value is written to standard output.
C17 · complete program
#include <stdio.h>
static int total(int maths, int science);
static int total(int maths, int science) {
return maths + science;
}
int main(void) {
printf("Total: %d\n", total(40, 35));
return 0;
}
Expected output
Total: 75
Run in C compiler →Follow the values through the code
C17 · code used in this explanation
#include <stdio.h>
static int total(int maths, int science);
static int total(int maths, int science) {
return maths + science;
}
int main(void) {
printf("Total: %d\n", total(40, 35));
return 0;
}
The prototype establishes two int parameters and an int result.
The definition performs the addition. The caller cannot invent a different contract simply because a prototype appears in another file.
Follow the worked calculation
Read the starting values
The prototype establishes two int parameters and an int result.
Perform the operation
The definition performs the addition. The caller cannot invent a different contract simply because a prototype appears in another file.
Check the observable result
Total: 75
Total: 75
Try a small variation
C17 · code used in this explanation
#include <stdio.h>
static int total(int maths, int science);
static int total(int maths, int science) {
return maths + science;
}
int main(void) {
printf("Total: %d\n", total(40, 35));
return 0;
}
Reuse the declared helper for 45 and 38.
Worked answer
The call satisfies the same two-integer contract; a shared module can serve different callers without duplicating its implementation.
C17 · complete program
#include <stdio.h>
static int total(int maths, int science);
static int total(int maths, int science) {
return maths + science;
}
int main(void) {
printf("Total: %d\n", total(45, 38));
return 0;
}
Expected output
Total: 83
Run in C compiler →Build a real three-file project
Now separate the runnable example into three files in the same folder. The header shares the function declaration. Its guard remembers that the header has already been included in the current source file’s compilation, so the guarded contents are not processed twice.
marks.h · C17
#ifndef SCHOOL_MARKS_H
#define SCHOOL_MARKS_H
int total(int maths, int science);
#endif
marks.c · C17
#include "marks.h"
int total(int maths, int science) {
return maths + science;
}
main.c · C17
#include <stdio.h>
#include "marks.h"
int main(void) {
printf("Total: %d\n", total(40, 35));
return 0;
}
marks.c supplies the function body. It includes its own header so the compiler can detect a conflict between that declaration and the definition. main.c includes the declaration so its call can be checked. Unlike the earlier single-file helper, this shared function has no static keyword: the linker must be able to find it from the other source file.
Unix-like shell command to compile and link both C source files:
cc -std=c17 -Wall -Wextra -Wpedantic main.c marks.c -o school
./schoolExpected output:
Total: 75If you build only main.c, the declaration can let compilation succeed, but the linker still needs the definition of total. The header is shared information; including it does not compile marks.c for you. Run this multi-file example in your local compiler; the course’s online editor accepts one source file.
Recognize the important boundaries
Including a header is not a substitute for linking the source or library that defines its declared functions.
Avoid conflicting declarations across files. A successful isolated translation cannot establish that incompatible cross-file types are a sound program.
Check your understanding
Choose the answer, then compare the reasoning for every option.
Use the idea independently
A header normally exposes declarations and types shared by source files. A function declaration describes its contract; one corresponding definition supplies its body for linking.
Continue with guards and macros.
Language reference: WG14 C11 committee draft. These examples use the C17-compatible subset of the explained language features.
Reaching the recap and completing the quizzes are separate milestones.