Question
Definition vs Declaration in C and C++: What’s the Difference?
Question
In C and C++, what is the difference between a declaration and a definition? The meaning of these two terms is confusing to me, and I want to understand how they differ in practice.
Short Answer
By the end of this page, you will understand what declarations and definitions mean in C and C++, how they relate to variables, functions, and types, and why the distinction matters when organizing code across multiple files.
Concept
A declaration tells the compiler that a name exists and describes its type.
A definition actually creates that thing or provides its full implementation.
In simple terms:
- A declaration says: "This exists somewhere. Here is what it looks like."
- A definition says: "Here it is. This is the real thing."
Why this matters
In real programs, code is usually split across multiple files:
- header files (
.h,.hpp) often contain declarations - source files (
.c,.cpp) often contain definitions
This lets many files know about the same variable or function without creating duplicates.
Variables
A variable declaration can introduce a variable without allocating storage, usually with extern:
extern int count;
This tells the compiler:
- there is an
intcalledcount - it is defined somewhere else
- do not create storage for it here
A variable definition creates the variable:
int count = 0;
This allocates storage for count.
Functions
A function declaration gives the function's name, return type, and parameters:
int add(int a, int b);
This tells the compiler how the function can be called.
A function definition includes the body:
int add(int a, int b) {
return a + b;
}
This is the actual implementation.
Important rule
Every definition is also a declaration, but not every declaration is a definition.
That is the key idea.
Types
For some types, the line can be only a declaration or both a declaration and a definition.
For example:
struct User;
This is a declaration of a struct type.
But this is a definition:
struct User {
int id;
char name[50];
};
Now the compiler knows the full layout of the type.
Mental Model
Think of a declaration like a table of contents entry in a book.
It tells you:
- the name of something
- what kind of thing it is
- where you can expect to use it
But it does not give the full content.
A definition is the actual chapter.
It contains the real material.
Analogy
Imagine a movie cast list:
- Declaration: "A character named Alex exists in this story."
- Definition: "Here is Alex, with dialogue, scenes, and actions."
The compiler needs declarations so it can understand references to names. The linker needs exactly the right set of definitions so the program can be built successfully.
Syntax and Examples
Core syntax
Variable declaration
extern int total;
Variable definition
int total = 10;
Function declaration
double multiply(double x, double y);
Function definition
double multiply(double x, double y) {
return x * y;
}
Type declaration
struct Item;
Type definition
struct Item {
int id;
double price;
};
Step by Step Execution
Consider this example:
#include <iostream>
int greet(); // declaration
int main() {
std::cout << greet() << "\n";
}
int greet() { // definition
return 42;
}
Step by step
-
The compiler reads
int greet();- It learns that a function named
greetexists. - It knows
greettakes no arguments and returnsint.
- It learns that a function named
-
The compiler reads
main().- Inside
main, it seesgreet()being called. - This is allowed because the function was already declared.
- Inside
Real World Use Cases
1. Header and source file organization
Large C and C++ programs usually place declarations in headers and definitions in source files.
Example:
database.hdeclaresconnect()database.cppdefinesconnect()
2. Sharing global configuration
A project may need one shared global variable:
// config.h
extern int maxConnections;
// config.cpp
int maxConnections = 100;
This avoids creating multiple copies.
3. Library development
Libraries expose declarations in public headers so other programs know how to call functions. The real code is provided by compiled object files or libraries.
4. Forward declarations to reduce dependencies
Sometimes developers declare a type before its full definition to avoid including heavy headers:
struct Engine;
This can speed up compilation and reduce coupling between files.
Real Codebase Usage
In real codebases, declarations and definitions are used as part of project structure and build organization.
Common patterns
Public interface in headers
Headers describe what is available:
// logger.h
void logMessage(const char* message);
Implementation in source files
Source files provide the real code:
// logger.cpp
#include <iostream>
void logMessage(const char* message) {
std::cout << message << "\n";
}
Shared globals with extern
Teams usually avoid globals when possible, but when they are used, the safe pattern is:
- declare in a header with
extern - define once in a source file
Forward declarations
Developers often forward-declare classes or structs when only a pointer or reference is needed:
Common Mistakes
1. Defining a global variable in a header
Broken example:
// settings.h
int timeout = 30;
If multiple source files include this header, each one gets its own definition, which usually causes linker errors.
Better
// settings.h
extern int timeout;
// settings.cpp
int timeout = 30;
2. Declaring a function but never defining it
Broken example:
int calculateTotal(int a, int b);
int main() {
return calculateTotal(2, 3);
}
If no definition exists, linking fails.
3. Confusing forward declaration with full type definition
Broken example:
Comparisons
| Concept | Declaration | Definition |
|---|---|---|
| Purpose | Introduces a name and type | Creates the object or provides full implementation |
| Variable example | extern int x; | int x = 5; |
| Function example | int f(); | int f() { return 1; } |
| Allocates storage? | Usually no | Yes, for objects |
| Contains function body? | No | Yes |
| Can appear multiple times? | Usually yes, if consistent | Usually only once per program |
Declaration vs forward declaration
A forward declaration is a specific kind of declaration that introduces something before its full definition appears.
Cheat Sheet
Quick rules
- A declaration introduces a name and type.
- A definition provides the actual object, function body, or full type.
- Every definition is a declaration.
- Not every declaration is a definition.
Common examples
extern int x; // declaration only
int x = 3; // definition
int add(int a, int b); // declaration
int add(int a, int b) { return a + b; } // definition
struct Node; // declaration
struct Node { int v; };// definition
Header/source pattern
// file.h
int work();
extern counter;
counter = ;
{
counter;
}
FAQ
Is a definition also a declaration?
Yes. A definition introduces the name, so it is also a declaration.
Why do header files usually contain declarations instead of definitions?
Because headers are included in many source files. Putting definitions there can create duplicate definitions.
What does extern mean for a variable?
It tells the compiler that the variable exists somewhere else and should not be created here.
Can a function be declared many times?
Yes, as long as the declarations are consistent. But it should normally be defined only once.
What is a forward declaration?
It is a declaration that introduces a type or function before the full definition is seen.
Why do I get a linker error even though I declared the function?
Because a declaration is not enough. The linker also needs the actual definition.
Can I create an object from a forward-declared struct or class?
No. The compiler needs the full definition to know its size and layout.
Mini Project
Description
Create a small multi-file C++ program that shares a function and a global variable across files. This demonstrates how declarations go in a header and definitions go in a source file.
Goal
Build a program that declares a function and a global variable in a header, defines them in a source file, and uses them from main.
Requirements
- Create a header file that declares one function and one global variable using
extern. - Create a source file that defines the function and the global variable.
- Create a
mainfile that includes the header and uses both. - Print the result of calling the function and reading the global variable.
Keep learning
Related questions
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.
Difference Between #include <...> and #include "..." in C and C++
Learn the difference between #include with angle brackets and quotes in C and C++, including search paths, examples, and common mistakes.
Difference Between ++i and i++ in C
Learn the difference between pre-increment and post-increment in C, how they behave, and which one to use in a for loop.