Question

C and C++ File Extensions: .c, .h, .cc, .cpp, .cxx, and .hpp

ccppfilenamesheader-filesnaming

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:

  • .h files are header files for C or C++ and usually contain declarations.
  • .c files contain C source code.
  • .cpp files 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 .c file is conventionally compiled as C.
  • A .cc, .cpp, or .cxx file is conventionally compiled as C++.
  • A .h or .hpp file 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, and enum declarations.
  • inline function 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 .cpp file is simply a .c file with extra features.

Mental Model

Think of file extensions as labels on folders in a workshop:

  • .c means “send this folder to the C workbench.”
  • .cpp, .cc, and .cxx mean “send this folder to the C++ workbench.”
  • .h and .hpp mean “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.

Take Quiz

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:

  • math_utils.h declares the add function.
  • math_utils.c defines the function.
  • main.c includes the declaration so the compiler knows how to call add.

A C++ project could use a similar layout:

// greeting.hpp
#pragma once

#include <string>

std::string makeGreeting(const std::string& name);
// greeting.cpp
#include "greeting.hpp"

std::string makeGreeting(const std::string& name) {
    return "Hello, " + name + "!";
}

Here, .hpp and .cpp communicate that the files are intended for C++. The equivalent .h and .cc naming would also be valid if the project chose that convention.

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:

  1. The compiler starts compiling main.cpp as C++ because of its extension.
  2. #include "score.hpp" effectively inserts the header's declaration into main.cpp during preprocessing.
  3. The compiler sees that bonusPoints takes an int and returns an int, so it can validate the call.
  4. The compiler separately compiles score.cpp as C++ and produces code for the function definition.
  5. The linker joins the compiled pieces together.
  6. At runtime, bonusPoints(90) returns 100, which is printed.

The header shares the function's interface; the source file provides its implementation.

Real World Use Cases

Common extension choices in real projects include:

  • C libraries: .h for public API headers and .c for implementations.
  • C++ applications: .hpp or .h for headers, plus .cpp, .cc, or .cxx for 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 .hpp files because users need to see the definitions at compile time.
  • Generated code: a tool may generate .c and .h files, while C++ generators may produce .cpp and .hpp files.
  • Large repositories: a team may choose .cc because it matches its style guide, while another chooses .cpp because it is familiar on its platform.

The extension itself is less important than consistent language selection and a predictable project layout.

Take Quiz

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 .cpp files.
  • 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 .cpp file, 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 */
#ifndef API_H
#define API_H

#ifdef __cplusplus
extern "C" {
#endif

int library_version(void);

#ifdef __cplusplus
}
#endif

#endif

This affects linkage for C++ callers; it does not make arbitrary C++ declarations valid C.

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
int square(int value) {
    return value * value;
}

If several .cpp files include this header, the linker can report multiple definitions.

Avoid it: put ordinary function definitions in one .cpp file, or mark appropriate small header-defined functions as inline.

// correct.hpp
inline int square(int value) {
    return value * value;
}

Using .hpp as if it changes C++ behavior

Changing widget.h to widget.hpp does not turn C code into C++ or add language features.

Avoid it: treat .hpp as a communication convention: “this header is intended for C++.”

Inconsistent naming

Using .cpp, .cc, and .cxx randomly in one small project makes navigation and build rules harder.

Avoid it: select one C++ source extension and use it consistently unless an external tool requires another.

Comparisons

ExtensionConventional meaningTypical language modeNotes
.cC implementation/source fileCThe standard, most widely recognized C source suffix.
.hHeader fileC or C++General-purpose header suffix; does not guarantee either language.
.cppC++ implementation/source fileC++Very common, especially on Windows and in beginner-oriented projects.
.ccC++ implementation/source fileC++Common in Unix-like and style-guide-driven codebases.
.cxxC++ implementation/source fileC++Another accepted convention, seen in some cross-platform projects.
.hppC++ header fileIncluded into C++ sourceOften used to distinguish C++-only headers from C-compatible .h headers.

.h versus .hpp

ChoiceBest when
.hThe header is C code, is C-compatible, or the project uses .h for all headers.
.hppThe project wants to clearly identify headers that require C++.

Neither extension changes how #include works.

.cpp versus .cc versus .cxx

These generally mean the same thing: C++ source code. Choose based on:

  • Your existing repository convention.
  • The conventions of a framework or organization.
  • What your build tools recognize automatically.

Do not choose based on a supposed language-feature difference; there is none.

Take Quiz

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, inline functions, and templates are common.
  • Use include guards or #pragma once in 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.

Do headers only contain declarations?

No. They commonly contain declarations, type definitions, macros, constants, inline functions, and template definitions. Avoid placing ordinary non-inline function definitions in headers unless you understand the linkage consequences.

Does .hpp automatically compile as C++?

A header is normally included by another source file rather than compiled independently. Its contents are interpreted according to the language mode of the source file that includes it.

Which C++ source extension should a new project choose?

Choose the extension preferred by your team, ecosystem, or starter template. If there is no existing convention, .cpp is a widely recognized choice.

Take Quiz

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.

Take Quiz

Keep learning

Related questions

View more