CInclude Guards

Include Guards

Because #include performs a literal text paste, including the same header more than once inside one translation unit pastes its content in more than once too — and if that header defines a struct, a type, or anything else the compiler will not let you redefine, that duplicate paste turns into a compile error.

How the Duplicate-Include Problem Happens

This usually happens indirectly: a.h includes common.h, b.h also includes common.h, and some main.c includes both a.h and b.h. Without protection, common.h gets pasted into main.c twice, and the compiler sees its type definitions declared twice.

C
/* common.h — no protection */
struct Point {
    int x;
    int y;
};

/* main.c */
#include "a.h"   /* a.h includes common.h */
#include "b.h"   /* b.h also includes common.h */

/* error: redefinition of 'struct Point' */
The Classic #ifndef Pattern

The traditional fix uses three directives working together as a one-time gate:

C
#ifndef COMMON_H
#define COMMON_H

struct Point {
    int x;
    int y;
};

#endif /* COMMON_H */
  • #ifndef COMMON_H — "only proceed if COMMON_H has not been defined yet"

  • The first time this header is included, COMMON_H is undefined, so the guard passes and #define COMMON_H immediately marks it as now defined

  • The struct definition, function prototypes, etc. are processed normally the first time

  • Any later #include of the same header (in the same translation unit) finds COMMON_H already defined, so #ifndef is false and everything up to #endif is skipped entirely

Note
The guard macro name (`COMMON_H` here) just needs to be unique across your whole project — a common convention is `PROJECTNAME_FILENAME_H`, uppercased, to avoid collisions between headers that happen to share a filename in different directories.
The Modern Alternative: #pragma once

C
#pragma once

struct Point {
    int x;
    int y;
};
Simpler, but not part of the official standard
`#pragma once` tells the compiler directly: never include this exact file more than once per translation unit. It is shorter, avoids picking a guard name entirely, and eliminates a class of bugs where two headers accidentally use the same guard macro. The catch is that `#pragma once` is not defined by the C standard — it is a compiler extension. In practice, though, it is supported by essentially every real-world compiler (GCC, Clang, MSVC), which is why it is widely used despite not being "official".

Approach

Pros

Cons

#ifndef / #define / #endif

Part of the C standard, works absolutely everywhere, maximum portability

More verbose, requires picking a unique guard name by hand

#pragma once

Short, no name to pick, avoids guard-name collisions

Not officially standardized (though universally supported in practice)

You will still see the #ifndef pattern in codebases that target strict portability guarantees, older toolchains, or coding standards written before #pragma once became ubiquitous. Both approaches solve the exact same problem — pick whichever your project's style guide prefers, and use it consistently.