The basics
What is an H file?
A .h file is a header file for C or C++ (and Objective-C). It declares what a piece of code offers, such as the functions in a library, their parameters and the types they use, so that other source files can call them. A source file uses a header by including it: #include "geometry.h".
Headers are everywhere in C and C++. stdio.h and stdlib.h come with every C compiler; operating systems ship thousands of them (windows.h, unistd.h); and every library you add brings its own. On Linux and macOS, system headers live in folders such as /usr/include; on Windows, in the Windows SDK and Visual Studio folders.
Three things that clear up common confusion:
- A header isn't compiled on its own. It's pasted into each
.cor.cppfile that includes it, and compiled as part of that file. - A header usually has no code that does anything. It describes; the matching
.cor.cppfile implements. Header-only libraries, below, are the exception. .hdoesn't tell you the language. The same extension is used for C and C++ headers; read the file (or look for.hpp) to know whether it needs a C++ compiler.
Anatomy
What's inside a header file
A header says what exists without, for the most part, saying how it works: types, function prototypes, constants and the occasional small inline function. Here is a typical C header that is also safe to use from C++, part by part.
/* geometry.h: points and the functions that measure them */
#ifndef GEOMETRY_H
#define GEOMETRY_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#define GEOMETRY_PI 3.14159265358979323846
typedef struct {
double x, y;
} point;
double distance(point a, point b);
double polygon_area(const point *corners, size_t count);
extern int geometry_calls;
static inline double square(double v)
{
return v * v;
}
#ifdef __cplusplus
}
#endif
#endif /* GEOMETRY_H */- 1
/* geometry.h: … */A comment
Often the documentation for the whole library: the header is the part users read.
- 2
#ifndef GEOMETRY_H / #define GEOMETRY_HThe include guard
The first time the header is included,
GEOMETRY_Hisn't defined, so the contents are read and the macro is defined. Any later include in the same file skips straight to the final#endif. - 3
#include <stddef.h>What the header itself needs
size_tis used below, so the header includes the header that defines it. A good header compiles on its own, whatever was included before it. - 4
#ifdef __cplusplus / extern "C" {C linkage for C++
C++ compilers encode parameter types into function names (name mangling); C compilers don't.
extern "C"makes C++ code look for the plain C names, so it can link to the compiled C library.__cplusplusis only defined by C++ compilers, so C never sees it. - 5
#define GEOMETRY_PI …A macro constant
Prefixed with the library's name, because macros ignore scopes and namespaces and can collide with anyone else's.
- 6
typedef struct { double x, y; } point;A type definition
Every file that uses
pointneeds to know its layout, so the definition goes in the header. Type definitions are allowed to repeat across files; a function or variable definition isn't. - 7
double distance(point a, point b);Function declarations
A prototype: name, parameters and return type, ending in a semicolon instead of a body. The body lives in
geometry.c, compiled once. - 8
extern int geometry_calls;A variable declaration
externsays the variable is defined somewhere else, in exactly one.cfile. Withoutextern, every file that includes the header would define its own. - 9
static inline double square(double v) { … }An inline function
Small functions can be defined in a header if they're
static inline(C) orinline(C++). Each including file gets a copy the compiler can inline, with no clash at link time. - 10
#endif /* GEOMETRY_H */The end of the guard
Closes the
#ifndef. The comment is a habit that makes long headers easier to read.
Under the hood
How #include works: declarations here, definitions there
#include is plain text substitution. Before compiling a source file, the preprocessor replaces the line with the full contents of the header, and repeats that for every header the header includes. The compiler then sees one long file. That's why a header is "compiled" once for every source file that includes it, and why big headers slow builds down.
#include <stdio.h>with angle brackets searches the system and compiler include folders.#include "geometry.h"with quotes searches the including file's own folder first, then the same folders as angle brackets.-I path(GCC, Clang) or/I path(MSVC) adds folders to search; this is how a project finds its libraries' headers.
The split between a header and its source file is the split between a declaration (this exists, and here is its type) and a definition (here it is). Every file that calls distance needs the declaration; only one may contain the definition, or the linker sees two copies.
/* geometry.c: the definitions */
#include <math.h>
#include "geometry.h"
int geometry_calls = 0;
double distance(point a, point b)
{
geometry_calls++;
return sqrt(square(b.x - a.x) + square(b.y - a.y));
}
/* … polygon_area … */
/* main.c: a user of the header */
#include <stdio.h>
#include "geometry.h"
int main(void)
{
point a = {0, 0}, b = {3, 4};
printf("%g\n", distance(a, b)); /* prints 5 */
return 0;
}
/* the build: */
/* cc -c geometry.c -> geometry.o, the code */
/* cc -c main.c -> main.o, calls distance() */
/* cc main.o geometry.o -lm -o demo -> the linker joins them */| Belongs in the header | Belongs in the .c or .cpp file |
|---|---|
| Function declarations (prototypes) | Function bodies |
Type definitions: struct, enum, typedef, classes | Variable definitions: int geometry_calls = 0; |
extern variable declarations | static helpers used only in that file |
| Macros and constants other files need | Macros only that file needs |
static inline / inline functions, templates (C++) | Large functions, even if called often |
#include lines the header itself needs | using namespace …; in C++: never in a header, where it leaks into every includer |
Conventions
Include guards vs #pragma once
A header often gets included twice in one source file, usually indirectly: main.c includes shapes.h and geometry.h, and shapes.h includes geometry.h too. Without protection, the second copy redefines point and the build fails with "redefinition of" errors. Every header needs one of these:
/* Include guard: standard C and C++, works everywhere */
#ifndef MYLIB_PARSER_H
#define MYLIB_PARSER_H
/* … declarations … */
#endif /* MYLIB_PARSER_H */
/* #pragma once: one line, not in the standard, supported by
GCC, Clang and MSVC */
#pragma once
/* … declarations … */| Include guard | #pragma once | |
|---|---|---|
| In the C and C++ standards | Yes | No, but GCC, Clang and MSVC all support it |
| Length | Three lines and a unique macro name | One line |
| Risk | Two headers that pick the same macro name silently hide each other | Can be fooled when the same file is reached through different paths, such as copies, symbolic links or network drives |
| Build speed | GCC and MSVC recognise the pattern and don't re-read the file | Same |
Either works in practice; many projects use #pragma once for new code and guards where portability to unusual compilers matters. Don't use both. For guard names, use the project and file name in capitals (MYLIB_PARSER_H), and don't start them with an underscore followed by a capital letter: such names are reserved for the compiler and standard library.
Related formats
.h vs .hpp, and other header extensions
The compiler doesn't care what an included file is called: #include pastes in any file. Extensions are for people and tools, and editors use them to pick C or C++ highlighting.
| Extension | What it is |
|---|---|
.h | A C header, or a C++ header in projects that use .h for both. Headers meant for both languages use extern "C", as in the anatomy above |
.hpp, .hh, .hxx | C++ headers: classes, templates and namespaces that a C compiler can't read. Usually paired with .cpp, .cc and .cxx sources |
No extension: <vector>, <string> | The C++ standard library's own headers. C library headers are available in C++ as <cstdio> as well as <stdio.h> |
.inl, .ipp, .tpp | Inline or template code, included at the end of a header to keep the declarations readable |
.gch, .pch | Precompiled headers: binary, compiler-specific files that speed up builds. Generated, never edited or shared |
.cppm, .ixx | C++20 module interfaces, the newer alternative to headers in C++ |
Packaging
Header-only libraries
Some libraries are nothing but headers: you copy the .h or .hpp file into your project and include it, with no separate library to build or link. Much of the C++ standard library and many popular C++ libraries work this way, because templates must be defined in headers anyway: the compiler needs the full code to generate a version for each type.
- In C++, functions and variables defined in a header must be
inline(or templates, orconstexpr). Without it, two.cppfiles including the header each define the function and linking fails with "multiple definition". - In C, single-file libraries often contain both halves: declarations normally, and the implementation only in the one source file that writes
#define LIBNAME_IMPLEMENTATIONbefore the include. - The trade-off is build time: every source file that includes the header compiles all of it again. Precompiled headers and C++20 modules exist to reduce that cost.
Troubleshooting
Header errors people hit most, and what they mean
| Message | Usual cause | Fix |
|---|---|---|
| fatal error: foo.h: No such file or directory | The header's folder isn't on the include path, or the library's development files aren't installed | Add -I path/to/include; on Linux install the library's -dev or -devel package |
| redefinition of 'struct point' | The same header included twice without a guard | Add an include guard or #pragma once |
| multiple definition of 'x' (MSVC: LNK2005) | A variable or non-inline function defined in a header included by several source files | Declare it extern in the header and define it in one source file; or make the function inline (C++) or static inline (C) |
| unknown type name 'size_t' / 'x' does not name a type | The header uses something it doesn't include itself, or two headers include each other in a circle | Make each header include what it uses; break circles with a forward declaration such as struct node; |
| undefined reference to 'stats_init(stats_t*)' | C++ calling a C library whose header has no extern "C" block. The parameter types in the message show C++ looked for a mangled name | Wrap the header's declarations in extern "C", as in the samples |
| undefined reference to 'distance' | The header was included but the source file that defines the function wasn't compiled or linked | Add the .c or .cpp file, or the library, to the build |
Why you don't compile a .h file
Run gcc geometry.h and GCC doesn't build a program: it writes a precompiled header, geometry.h.gch. Build tools compile the .c and .cpp files, and the headers come along through #include. To check that a header is self-contained, compile a source file that includes only that header.
How to
How to open, read and edit a header file
- Read it: any text editor works, and a browser shows it as text. A library's headers are often its best reference: they list every function with its parameters.
- Edit it: VS Code, Visual Studio, CLion, Xcode, Vim and Emacs all understand headers. "Go to definition" in an IDE jumps from a declaration in the header to the code in the source file.
- Find where something is declared: in a terminal,
grep -rn "distance(" include/searches a folder of headers. - See what the compiler sees:
gcc -E file.cprints a source file after preprocessing, with every header pasted in. Expect it to be thousands of lines long.
Opening a header is safe: it's text, and nothing runs. Headers do become part of whatever is compiled with them, so a header from an untrusted source deserves the same review as any other code you build, including its macros, which can hide code behind innocent-looking names.
Free downloads
Sample header files to download
Free sample header files, with the source files that use them, for testing compilers, IDEs, syntax highlighting and code viewers. They build with GCC and Clang, as C and as C++, with warnings on and none reported. Download all five into one folder to build them.
Loading…What's inside sample-header.h
The header is commented: open it in a text editor and each numbered comment marks one of these parts. Its comments also give the build commands that connect it to the other samples.
Comment 1: the include guard
#ifndef SAMPLE_HEADER_H/#define SAMPLE_HEADER_H.sample-main.cincludes the header twice on purpose to show the guard working.Comment 2: the header's own includes
stdbool.handstddef.h, forboolandsize_t, so the header compiles whatever was included before it.Comments 3 and 9: extern "C"
Opened and closed inside
#ifdef __cplusplus, so the C functions link fromsample-main.cpp. The build check for these samples confirms that removing it makes the C++ link fail.Comments 4 and 5: macros and a type
A version string, a size limit, and a
stats_tstruct that callers can create as an ordinary local variable.Comment 6: function declarations
Five prototypes ending in semicolons. Their bodies are in
sample-header.c.Comment 7: an extern variable
extern const char stats_library_name[];, defined once insample-header.c.Comments 8 and 10: an inline function and the end of the guard
A
static inlinefunction, one of the few function definitions that belongs in a C header, then the closing#endif.
All sample H files
Commented C header with an include guard
sample-header.h · 2.6 KB (2,627 bytes)
The header of a tiny statistics library: an include guard, its own includes,
extern "C"for C++, macros, a struct, prototypes, anexternvariable and astatic inlinefunction, with numbered comments explaining each part.- Checking syntax highlighters and IDEs on headers
- Teaching what belongs in a header
The matching source file
sample-header.c · 1.5 KB (1,531 bytes)
The definitions behind
sample-header.h: it includes its own header first, defines theexternvariable once and implements the five functions.- Showing how a header and its source file pair up
- Building the C and C++ examples
C program that uses the header
sample-main.c · 950 bytes
Includes the header twice to show the guard working, then calls the library. Build:
cc -std=c17 sample-main.c sample-header.c -o stats-c.- A two-file C build test
- Include-guard demonstration
C++ program that uses both headers
sample-main.cpp · 1.3 KB (1,331 bytes)
Calls the C library through its
extern "C"header, linked againstsample-header.ocompiled by a C compiler, and uses the header-only C++ library to draw a text bar chart.- Testing mixed C and C++ builds
- Checking that `extern "C"` linkage works with your toolchain
Header-only C++ library (#pragma once)
sample-header-only.hpp · 1.5 KB (1,545 bytes)
A
.hppheader guarded with#pragma once, containing a function template, aninlinefunction and aninline constexprvariable: everything a header-only library needs, with comments on why each is allowed in a header.- Comparing `#pragma once` with include guards
- Testing tools that treat `.hpp` differently from `.h`
Ways to test with them
- Mixed C and C++ builds: compile
sample-header.cwith a C compiler and link it intosample-main.cppwith a C++ compiler, as the comments describe. If linking fails, check that both compilers are from compatible toolchains. - Self-contained headers: compile a file containing only
#include "sample-header.h"as C and as C++; it should produce no errors or warnings. - Syntax highlighting: open
sample-header.handsample-header-only.hppin your viewer; a.hfile can be C or C++, so check which highlighting it picks. - Upload filters: some systems block or rename source files. Try the samples to see whether
.h,.hppand.cfiles pass through unchanged.
Free to use for testing, teaching and demos, commercially or not, with no attribution needed. A link back to this page is always appreciated.
Put it online
Have a header file? Give it a link.
Drop a .h file on 99helpers and it gets its own web address. Anyone who opens the link reads it as plain text in their browser: it is never compiled or run, which makes it an easy way to share an API or a library's declarations for review.
Questions
H files, frequently asked
What is a .h file?
A header file for C or C++. It declares functions, types and constants so that .c and .cpp files can include it with #include and use them.
How do I open an H file?
With any text editor or code editor, such as VS Code, Notepad, Visual Studio or Xcode. It's plain text.
Can I run or compile a .h file?
No. A header isn't a program and isn't compiled on its own: you compile the .c or .cpp files that include it. Passing a header straight to GCC makes a precompiled header (.gch), not a program.
What's the difference between .h and .c files?
The .h file declares what exists (function prototypes, types, constants); the .c file defines it (the function bodies). Other files include the .h and are linked with the compiled .c.
What's the difference between .h and .hpp?
Only convention. .hpp signals a C++-only header; .h is used for C headers and, in many projects, for C++ headers too. Compilers treat them the same way when they're included.
Should I use #pragma once or include guards?
Either. Include guards are standard and work everywhere; #pragma once is shorter and supported by GCC, Clang and MSVC, but isn't part of the C or C++ standard. Pick one per project.
What is a header-only library?
A library delivered entirely as header files: you include it and there's nothing separate to build or link. Common in C++, where templates have to be defined in headers anyway.
Why do I get "multiple definition" errors from a header?
Something is defined, not just declared, in a header that several source files include. Declare variables extern in the header and define them in one source file; make header functions inline (C++) or static inline (C).
Related formats
Other file types explained
Keep going
Related
Sources
- GCC: The C Preprocessor, Once-Only Headers
- Microsoft Learn: the once pragma
- Clang-Tidy: portability-avoid-pragma-once
- GCC: Options controlling the kind of output (header suffixes, .gch)
- ISO/IEC 9899:2024, Programming languages: C (ISO)
Last reviewed 27 October 2026.