Include Guards
Part of the Object Oriented Programming section of Coddy's C journey — lesson 2 of 61.
When a header file gets included multiple times in a project, the compiler sees the same declarations repeatedly, causing errors. This commonly happens when multiple files include the same header, or when headers include each other. Include guards solve this problem.
An include guard uses three preprocessor directives to ensure a header's contents are processed only once:
// math_utils.h
#ifndef MATH_UTILS_H
#define MATH_UTILS_H
int add(int a, int b);
#endif
Here's how it works: #ifndef MATH_UTILS_H checks if the symbol MATH_UTILS_H has not been defined yet. If it hasn't, the preprocessor continues and immediately defines it with #define MATH_UTILS_H. Everything between this point and #endif is included in the compilation.
The second time this header is included, MATH_UTILS_H is already defined, so the entire block is skipped. The guard name is typically the filename in uppercase with underscores replacing dots and special characters.
Every header file you create should have include guards. This is a standard practice that prevents compilation errors and makes your code safe to include from anywhere in your project.
Challenge
EasyLet's protect a header file from double inclusion by adding include guards. You'll build on the greeting utility from the previous lesson, but this time ensure the header is safe to include multiple times.
You'll create two files:
greet.h: Your header file containing the function declaration forgreet. This time, wrap the entire contents with include guards using the symbolGREET_H.main.c: Your main file that includes the header, implements thegreetfunction, and calls it frommain().
The greet function should accept a const char* parameter for the name and print:
Hello, Alice!Your header file should follow this structure:
#ifndef GREET_H
#define GREET_H
// function declaration here
#endifYou will receive one input: a name (string).
Print the greeting message exactly as shown in the format above, replacing Alice with the provided name.
Cheat sheet
Include guards prevent header files from being processed multiple times during compilation, which would cause errors.
An include guard uses three preprocessor directives:
#ifndef HEADER_NAME_H
#define HEADER_NAME_H
// header contents here
#endif
#ifndef checks if a symbol has not been defined. If undefined, #define defines it and the contents are processed. On subsequent inclusions, the symbol is already defined, so the entire block is skipped.
The guard name is typically the filename in uppercase with underscores replacing dots and special characters.
Every header file should have include guards as standard practice.
Try it yourself
#include <stdio.h>
#include "greet.h"
// TODO: Implement the greet function that prints "Hello, <name>!"
int main() {
char name[100];
scanf("%s", name);
// TODO: Call the greet function with the name
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