Source Files
Part of the Object Oriented Programming section of Coddy's C journey — lesson 3 of 61.
So far, we've placed function declarations in header files, but the actual function code (the definition) has lived in the main file. The next step in modular programming is moving those definitions into their own source files (.c files).
This creates a clean three-part structure: the header declares functions, a separate source file defines them, and main simply uses them. Here's how it looks:
// math_utils.h
#ifndef MATH_UTILS_H
#define MATH_UTILS_H
int add(int a, int b);
#endif
// math_utils.c
#include "math_utils.h"
int add(int a, int b) {
return a + b;
}
// main.c
#include <stdio.h>
#include "math_utils.h"
int main() {
printf("%d\n", add(5, 3));
return 0;
}
Notice that math_utils.c includes its own header. This ensures the function definition matches the declaration—if they don't match, the compiler will catch the error. The main file only needs to include the header to use the function; it doesn't need to know how add works internally.
This separation keeps implementation details hidden and allows you to modify function logic without touching files that use those functions.
Challenge
EasyLet's build a simple math utility by organizing your code into the proper three-file structure: a header for declarations, a source file for implementations, and a main file that uses them.
You'll create three files:
math_ops.h: Your header file containing function declarations for two operations:multiplyandsubtract. Both functions take two integers and return an integer. Don't forget to include guards using the symbolMATH_OPS_H.math_ops.c: Your source file containing the actual implementations ofmultiplyandsubtract. This file should include its own header to ensure declarations match definitions.main.c: Your main file that includes the header and uses both functions to perform calculations.
The multiply function should return the product of two integers, and subtract should return the first integer minus the second.
You will receive two integer inputs: a and b.
In your main function, print the results of both operations on separate lines:
Product: {result of multiply}
Difference: {result of subtract}For example, with inputs 8 and 3, the output would be:
Product: 24
Difference: 5Cheat sheet
Function definitions can be moved from the main file into separate source files (.c files), creating a three-part modular structure:
- Header file (
.h): Contains function declarations - Source file (
.c): Contains function definitions - Main file (
main.c): Uses the functions
Example structure:
// math_utils.h
#ifndef MATH_UTILS_H
#define MATH_UTILS_H
int add(int a, int b);
#endif
// math_utils.c
#include "math_utils.h"
int add(int a, int b) {
return a + b;
}
// main.c
#include <stdio.h>
#include "math_utils.h"
int main() {
printf("%d\n", add(5, 3));
return 0;
}
The source file (.c) should include its own header to ensure the function definition matches the declaration. The main file only needs to include the header to use the functions, keeping implementation details hidden.
Try it yourself
#include <stdio.h>
#include "math_ops.h"
int main() {
int a, b;
scanf("%d", &a);
scanf("%d", &b);
// TODO: Call the multiply function with a and b, store the result
// TODO: Call the subtract function with a and b, store the result
// TODO: Print the results in the format:
// Product: {result of multiply}
// Difference: {result of subtract}
return 0;
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Modular Programming Basics
Header FilesInclude GuardsSource FilesStatic FunctionsRecap: Modular Calculator4Encapsulation
Opaque Pointers ConceptDefining Opaque StructsGetters and SettersValidation in SettersRecap: Secret Box2Objects and Methods
Structs as ObjectsThe 'Self' PointerConst CorrectnessPointer vs ValueHelper MethodsRecap: Point Manager5Project: Simple Bank Account
Project SetupImplementation of Account3Object Lifecycle
Constructor PatternDestructor PatternStack InitializationDeep CopyRecap: String Wrapper6Inheritance via Composition
Struct EmbeddingThe First Member RuleAccessing Parent MembersUpcastingRecap: Shape Hierarchy