Question
What are the differences between the .c, .h, .cc, .cpp, .cxx, and .hpp file extensions used in C and C++ projects?
I understand the common convention that:
.hfiles are header files for C or C++ and usually contain declarations..cfiles contain C source code..cppfiles contain C++ source code.
However, extensions such as .hpp, .cc, and .cxx are also common. What do these extensions conventionally mean, and when should each be used?
Short Answer
C and C++ source-file extensions are mostly conventions, not language rules. In practice, .c normally identifies C source, while .cc, .cpp, and .cxx normally identify C++ source. Likewise, .h is a general header extension and .hpp often signals a C++-only header. The most important rule is to choose a convention, configure your build tools correctly, and use it consistently.
Concept
A file extension helps people, editors, compilers, and build systems decide how to treat a file. It is not part of the C or C++ language syntax.
The key distinction is usually the language mode:
- A
.cfile is conventionally compiled as C. - A
.cc,.cpp, or.cxxfile is conventionally compiled as C++. - A
.hor.hppfile is a header: code intended to be included by other source files with#include.
Different compilers and build systems recognize different extension defaults. For example, a command-line compiler may choose C or C++ mode from the filename, while a build system such as CMake can explicitly set the language regardless of the suffix.
Headers are not limited to declarations. They often contain:
- Function declarations and type definitions.
- Constants and macros.
struct,class, andenumdeclarations.inlinefunction definitions.- C++ template definitions, which generally must be visible to code that uses them.
A C++ compiler can compile many C-like programs, but C and C++ are distinct languages. Some valid C programs are not valid C++, and some valid C++ programs are not valid C. Therefore, do not assume a file is simply a file with extra features.
Mental Model
Think of file extensions as labels on folders in a workshop:
.cmeans “send this folder to the C workbench.”.cpp,.cc, and.cxxmean “send this folder to the C++ workbench.”.hand.hppmean “this folder contains shared instructions that other folders can reference.”
The labels do not change the paper inside the folder. A build tool can be told to use a different workbench. But clear labels prevent people and tools from making the wrong assumption.
Syntax and Examples
The preprocessor includes a header with #include.
/* math_utils.h */
#ifndef MATH_UTILS_H
#define MATH_UTILS_H
int add(int left, int right);
#endif
/* math_utils.c */
#include "math_utils.h"
int add(int left, int right) {
return left + right;
}
/* main.c */
#include <stdio.h>
#include "math_utils.h"
int main(void) {
printf("%d\n", add(2, 3));
return 0;
}
In this C example:
Step by Step Execution
Consider this C++ example:
// score.hpp
#pragma once
int bonusPoints(int score);
// score.cpp
#include "score.hpp"
int bonusPoints(int score) {
return score + 10;
}
// main.cpp
#include <iostream>
#include "score.hpp"
int main() {
std::cout << bonusPoints(90) << '\n';
}
When the program is built:
- The compiler starts compiling
main.cppas C++ because of its extension. #include "score.hpp"effectively inserts the header's declaration into during preprocessing.
Real World Use Cases
Common extension choices in real projects include:
- C libraries:
.hfor public API headers and.cfor implementations. - C++ applications:
.hppor.hfor headers, plus.cpp,.cc, or.cxxfor implementations. - Cross-platform libraries: C headers may expose an API usable from both C and C++.
- Template-heavy C++ libraries: template definitions are often placed entirely in
.hppfiles because users need to see the definitions at compile time. - Generated code: a tool may generate
.cand.hfiles, while C++ generators may produce.cppand.hppfiles. - Large repositories: a team may choose
.ccbecause it matches its style guide, while another chooses.cppbecause it is familiar on its platform.
The extension itself is less important than consistent language selection and a predictable project layout.
Real Codebase Usage
Teams normally define an extension policy in their style guide and enforce it through build configuration, editor settings, and code review.
A typical C++ layout might look like this:
project/
├── include/
│ └── inventory/
│ └── item.hpp
├── src/
│ └── item.cpp
└── tests/
└── item_test.cpp
Useful real-project patterns include:
- Public versus private headers: public headers live under an
include/directory; implementation-only headers may stay near.cppfiles. - Include guards or
#pragma once: prevent a header from being processed more than once in one translation unit. - Include your matching header first: in a
.cppfile, including its own header early can reveal missing includes in that header.
// item.cpp
#include "inventory/item.hpp" // Check this header is self-contained.
#include <stdexcept>
- C-compatible headers: when a header is consumed by both languages, C++ code commonly wraps declarations in
extern "C".
/* api.h */
{
;
}
Common Mistakes
Treating extensions as universal compiler rules
Not every tool recognizes every extension in the same way. A compiler or build system may require configuration for an uncommon suffix.
Avoid it: check your compiler and build-tool documentation, and make the language explicit when necessary.
Mixing C and C++ accidentally
// file.c
#include <iostream> // Not a C standard header.
A .c file is normally compiled as C, so C++ headers and syntax will fail.
Avoid it: rename and compile the file as C++ only if the file is meant to be C++.
Assuming all C code is valid C++
Some C constructs have different rules in C++. For example, C permits implicit conversion from void* in assignment, while C++ does not.
/* Valid C, but not valid C++ without a cast. */
int *values = malloc(10 * sizeof *values);
Avoid it: compile C files with a C compiler and C++ files with a C++ compiler. Do not rely on accidental compatibility.
Putting non-inline function definitions in a widely included header
// broken.hpp
{
value * value;
}
Comparisons
| Extension | Conventional meaning | Typical language mode | Notes |
|---|---|---|---|
.c | C implementation/source file | C | The standard, most widely recognized C source suffix. |
.h | Header file | C or C++ | General-purpose header suffix; does not guarantee either language. |
.cpp | C++ implementation/source file | C++ | Very common, especially on Windows and in beginner-oriented projects. |
.cc | C++ implementation/source file | C++ | Common in Unix-like and style-guide-driven codebases. |
.cxx | C++ implementation/source file |
Cheat Sheet
.c→ conventionally a C source file..cc,.cpp,.cxx→ conventionally C++ source files..h→ a header usable for C, C++, or both, depending on its contents..hpp→ conventionally a C++-only header.- Extensions are conventions interpreted by compilers and build tools; they are not language syntax.
- Headers can contain more than declarations: macros, types, constants,
inlinefunctions, and templates are common. - Use include guards or
#pragma oncein headers. - Define ordinary non-inline functions in one source file, not in a header included by many source files.
- A C++ compiler is not a drop-in replacement for a C compiler; the languages differ.
- Pick one C++ source extension (
.cpp,.cc, or.cxx) per project and stay consistent.
FAQ
Is there a real difference between .cpp, .cc, and .cxx?
Usually no. They are all common conventions for C++ source files. The practical difference is whether your compiler, editor, and build system recognize the selected extension automatically.
Should I use .h or .hpp for C++ headers?
Either is valid. Use .hpp if your project wants to signal that the header requires C++. Use .h if that is the existing project convention or if the header should also work from C.
Can a .h file contain C++ classes?
Yes. The extension does not restrict its contents. However, a header containing C++ classes cannot be compiled as C.
Can I compile a .c file as C++?
Yes, if you explicitly configure the compiler or build system to treat it as C++. Renaming it to .cpp, .cc, or .cxx is usually clearer unless an external constraint requires .c.
Why are template implementations often in .hpp files?
C++ templates usually need their full definitions visible where they are instantiated. Keeping declarations and definitions in a header is the simplest common approach.
Mini Project
Description
Create a small C++ utility split into a header and an implementation file. This demonstrates the usual separation between a public interface (.hpp) and implementation (.cpp), while showing how #include connects them.
Goal
Build a program that converts a temperature from Celsius to Fahrenheit using a function declared in a header and defined in a source file.
Requirements
Create a temperature.hpp header that declares a conversion function.
Keep learning
Related questions
2D Array Loop Order and Cache Performance in C
Learn why swapping nested loops changes 2D array performance in C, using row-major memory layout, cache locality, and practical benchmarks.
Array-to-Pointer Conversion in C and C++ Explained
Learn what array-to-pointer conversion means in C and C++, how array decay works, and how it differs from a pointer to an array.
Building More Fault-Tolerant Embedded C++ Applications for Radiation-Prone ARM Systems
Learn practical C++ and compile-time techniques to reduce soft-error damage in embedded ARM systems exposed to radiation.