H File Documentation
Summary
A C/C++/Objective-C Header File is a plain-text source file holding declarations, function prototypes, struct and class definitions, constants and macros, that other source files share with an #include directive. It is part of a program’s source code, not something you run. Its MIME type is text/x-c. Read or edit a .h file in any text or code editor (VS Code, Notepad++, Vim, Xcode); it only does anything once a compiler builds it with the matching .c or .cpp files.
Technical details
| Feature | Value |
|---|---|
| Full name | C/C++/Objective-C Header File |
| File extension | .h |
| MIME type | text/x-c |
| Format type | Plain-text source code (header) |
| Language | C, C++ and Objective-C (also .hpp, .hxx, .hh for C++) |
| Developer | C/C++ language convention; ISO/IEC standards |
| Introduced | 1972 (C language and its #include convention) |
| Open standard | Yes — text file, language is ISO-standardised |
| Encoding | ASCII / UTF-8 text (no signature) |
| Magic number | None — identified by extension and content |
| Typical opening | Include guard (#ifndef) or #pragma once, or a comment |
| Holds | Prototypes, types, struct/class definitions, macros, constants |
| Pulled in by | #include directive in .c / .cpp source |
| Processed by | The C/C++ preprocessor, before compilation |
| Compiled with | GCC, Clang/LLVM, MSVC (not compiled alone) |
| Free editors | VS Code, Notepad++, Vim, Emacs, Xcode |
| Related extensions | .c, .cpp, .hpp, .hxx, .cc, .cxx, .m |
| Specification | cppreference.com/w/cpp/header |
What is a .h file?
A .h file is a C/C++/Objective-C Header File: a plain-text source file holding declarations that several source files need to share. The #include header convention dates from the earliest C, created by Dennis Ritchie at Bell Labs around 1972, and it is the mechanism that lets a program built from many source files agree on the same interfaces. A header typically contains function prototypes, type and struct definitions, class definitions in C++, enumerations, constants and preprocessor macros. Objective-C uses the same .h headers to declare its @interface classes, and some C++ projects prefer .hpp, .hxx or .hh, but the role is identical.
The key thing to understand is that a header does nothing on its own. It is not compiled directly and it is not a program. It only has meaning when a source file pulls it in with #include and a compiler then builds them together. To see why, you have to look at what the preprocessor actually does with an #include line.
The #include directive: literal text substitution
When the C or C++ preprocessor encounters an #include line, it finds the named file and copies its entire text into the current file at that point, before the compiler proper ever runs. This is pure textual substitution. There is no linking, no import of symbols, no namespace: the header’s bytes are spliced in as if you had typed them.
#include <stdio.h> // search the system include paths
#include "config.h" // search the current directory first, then system paths
The two bracket forms differ only in search order. Angle brackets < > tell the preprocessor to look on the system and toolchain include paths, used for standard and library headers such as <stdio.h>. Double quotes " " tell it to look in the including file’s own directory first and then fall back to the system paths, used for a project’s own headers. When the compiler reports fatal error: foo.h: No such file or directory, it means it walked every path it knows and never found foo.h; the header is missing or its folder is not on the include path.
Include guards and the double-inclusion problem
Because #include is literal text substitution, a header reached through two different paths would be pasted in twice, and redefining a struct or a type in the same translation unit is an error. Headers defend against this with an include guard:
#ifndef WIDGET_H
#define WIDGET_H
struct Widget { int id; double value; };
void widget_init(struct Widget *w);
#endif /* WIDGET_H */
The first time this header is included, WIDGET_H is not yet defined, so the preprocessor keeps the body and defines WIDGET_H. Any later inclusion in the same translation unit finds WIDGET_H already defined and skips straight to #endif, so the declarations appear exactly once. The macro name is chosen to be unique, usually derived from the file name. The common modern shorthand is #pragma once, a single line at the top of the file that tells the compiler to include the file at most once. It is not part of the ISO standard but is supported by GCC, Clang and MSVC, and it avoids the risk of two headers accidentally sharing the same guard macro.
Declaration versus definition: header versus source
The division of labour between a .h and its matching .c or .cpp is the heart of the C build model. A declaration announces that something exists and gives its shape; a definition provides the actual body or storage. Headers hold declarations so that many source files can share one interface; the source file holds the single definition.
/* math_utils.h -- declaration (the interface) */
int add(int a, int b);
/* math_utils.c -- definition (the implementation) */
#include "math_utils.h"
int add(int a, int b) { return a + b; }
This is the “one definition rule” in practice: the prototype can appear in a header included by hundreds of files, but the function body must be defined exactly once across the whole program, and the linker resolves each call to that single definition. Putting a full function definition in a header, and then including it from two source files, produces a duplicate-symbol link error, which is a classic beginner mistake.
The C++ exception: templates and inline functions
C++ complicates the tidy rule above. A template is not code until it is instantiated for concrete types, and the compiler needs the template’s full body visible at every point of use to generate that code. So template definitions live in headers, not in a separate source file. The same applies to functions marked inline and to constexpr functions, whose definitions are allowed in headers precisely because inline exempts them from the one-definition rule across translation units. This is why C++ headers are often much larger than C headers: they carry real implementation, not just prototypes, which is one of the reasons C++ builds can be slow.
Macros and conditional compilation in headers
Headers are also where #define macros and conditional compilation live. A macro can define a constant (#define MAX_LEN 256) or a function-like text substitution, and because the preprocessor expands macros before compilation, a macro in a header changes how every file that includes it is compiled. Conditional blocks (#ifdef, #if defined(...), #else, #endif) let one header adapt to different platforms or build configurations, for example exposing different declarations on Windows versus Linux. This power is also a caution for developers: a header can silently redefine behaviour in every dependent file, so a badly written macro in a widely included header has wide reach.
How a build actually uses a header
Putting it together, a normal build has three stages. The preprocessor expands every #include and macro, producing a single flat translation unit of pure C or C++ for each source file. The compiler turns each translation unit into an object file, checking that calls match the prototypes the headers declared. The linker then joins the object files, matching each call to the one real definition and producing an executable. Headers matter in the first two stages: they give every source file the same view of the interfaces, and they let the compiler check your calls without seeing the implementation. A header is thus a compile-time contract, shared by textual inclusion, and resolved to real code by the linker.
Frequently asked questions
What is the difference between a .h and a .c file?
The header (.h) holds declarations: prototypes, types, constants and macros that describe an interface. The .c or .cpp file holds the definitions, the actual code that does the work. Source files #include the header so they all agree on the same definitions. You compile the .c/.cpp files; you do not compile a header on its own.
What is the difference between .h and .hpp?
Both are headers and compilers treat them the same. .h is the traditional C and shared C/C++ extension; .hpp, .hxx and .hh are conventions some projects use to mark a header as C++-only. The choice is a style decision, not a technical one.
Why do I get “fatal error: xxx.h: No such file or directory”?
The compiler could not find a header your code includes. Either the file is missing, or the folder that contains it is not on the include path. Install the required library or SDK, or add its include directory to your build settings (for example with a -I flag for GCC or Clang).
References
- cppreference — Source file inclusion (#include)
- cppreference — C++ standard library headers
- Visual Studio Code — C/C++ editing and tooling
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.