#ifndef Include Guards in C

Jinku Hu Oct 12, 2023
  1. Use ifndef Include Guard to Protect Against Multiple Inclusion of Header Files in C
  2. Use ifndef Directive to Ensure Macros Aren’t Defined Multiple Times in C
#ifndef Include Guards in C

This article will demonstrate multiple methods of how to use #ifndef include guards in C.

Use ifndef Include Guard to Protect Against Multiple Inclusion of Header Files in C

Header files in C are used to define the interface for the functions implemented in the source file with the same name. The interface usually includes function prototypes, definitions for publicly accessible data structures, and some other miscellaneous stuff.

Note that header files may be included in the source file multiple times, leading to compiler errors. Usually, this is prevented with the #ifndef preprocessor directive, which is called wrapper #ifndef.

When the contents of the header file are enclosed in the structure shown in the following example, where the directive #ifndef MY_GUARD is the starting point and #endif the ending. ifndef directive checks if the MY_GUARD macro is defined, if not it continues and defines it with the next directive.

In case the user includes the same header for the second time, the ifndef directive will evaluate false and ignore the code before the #endif directive. As a result, the compiler will get only one copy of the code from this header file and translate it successfully.

#include <stdio.h>

#ifndef MY_GUARD
#define MY_GUARD 1

#define PER(D) #D
#define JOIN(A, B) (A##B)
#define JOINX(A, B) JOIN(A, B)

int power(int base, int n) {
  int p = base;
  for (size_t i = 0; i < n; i++) {
    p *= base;
  }
  return p;
}
#endif

Another method to accomplish the same results is to include #pragma once directive in the header file. The preprocessor scans those header files only once and guarantees that they are not read again.

One downside of the following method is that it has low portability across the different preprocessors, so one might want to stick with the wrapper #ifndef method to ensure better flexibility of the codebase.

#include <stdio.h>

#pragma once

#define PER(D) #D
#define JOIN(A, B) (A##B)
#define JOINX(A, B) JOIN(A, B)

int power(int base, int n) {
  int p = base;
  for (size_t i = 0; i < n; i++) {
    p *= base;
  }
  return p;
}

Use ifndef Directive to Ensure Macros Aren’t Defined Multiple Times in C

Alternatively, we can use the ifndef directive to check if the given macro expression has already been defined. The logic works exactly as in the previous example; if the expression is not defined, the next #define directive is processed accordingly.

The only line between the #ifndef and #endif is one macro definition, meaning that in case the condition is false, just the given macro is definition is skipped.

#include <stdio.h>
#include <stdlib.h>

#define PER(D) #D

#ifndef DLEVEL
#define DLEVEL 6
#endif

int main() {
  for (int j = 0; j < DLEVEL; ++j) {
    printf("%s\n", PER(stringify this));
  }

  exit(EXIT_SUCCESS);
}
Author: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook