Question
Difference Between #include <...> and #include "..." in C and C++
Question
What is the difference between using angle brackets and double quotes in a C or C++ #include directive?
#include <filename>
#include "filename"
Specifically, how does the compiler or preprocessor decide where to look for the file in each case, and when should each form be used?
Short Answer
By the end of this page, you will understand how #include <...> and #include "..." work in C and C++, how the preprocessor searches for header files, when to use each form, and what common mistakes to avoid when organizing your code and dependencies.
Concept
In C and C++, #include tells the preprocessor to copy the contents of a header file into the current source file before compilation.
The two common forms are:
#include <header>
#include "header"
The main difference is where the preprocessor searches first.
#include <header>is typically used for system headers or library headers.#include "header"is typically used for your own project headers.
What usually happens
#include <header>
The preprocessor searches in the compiler's configured system include directories.
Examples:
#include <iostream>
#include <vector>
#include <stdio.h>
These files are normally provided by the standard library or installed libraries.
#include "header"
The preprocessor usually searches:
- The current file's directory, or the directory of the including file
- Then the normal include directories
Examples:
#include "config.h"
#include "user.h"
#include "math_utils.h"
These files are usually part of your own codebase.
Why this matters
This affects:
- how your project is structured
- whether the correct file is found
- portability across compilers and build systems
- avoiding accidental inclusion of the wrong header
Important note
The exact search rules can vary slightly by compiler and build system. However, the common convention is:
- angle brackets: system or external library headers
- quotes: local project headers
That convention is followed in most real C and C++ projects.
Mental Model
Think of #include like looking for a book.
#include <...>means: go to the library shelves first.#include "..."means: check my desk first, then go to the library if needed.
Your own notes are usually on your desk, so quotes make sense for project files. Standard reference books live in the library, so angle brackets make sense for system headers.
This mental model helps explain why the two forms often find different files even if the names are the same.
Syntax and Examples
Core syntax
#include <header>
#include "header"
Example 1: Standard library header
#include <iostream>
int main() {
std::cout << "Hello\n";
}
Why angle brackets?
iostream is a standard library header. The compiler already knows where standard library headers are installed, so angle brackets are the normal choice.
Example 2: Project header
Suppose your project has this file:
// math_utils.h
int add(int a, int b);
Then you include it like this:
#include "math_utils.h"
#include <iostream>
int add(int a, int b) {
return a + b;
}
int main() {
std::cout << add(2, 3) << "\n";
}
Why quotes?
math_utils.h is part of your project, so you usually want the preprocessor to look in your local source directory first.
Example 3: External library header
#include <curl/curl.h>
This is commonly written with angle brackets because the header usually comes from an installed third-party library, not from the current source folder.
General rule of thumb
- Use
"..."for headers you wrote or that live inside your project. - Use
<...>for standard library or installed external library headers.
Step by Step Execution
Consider this file structure:
project/
├── main.cpp
└── config.h
And main.cpp contains:
#include "config.h"
#include <iostream>
int main() {
std::cout << "Program started\n";
}
What happens step by step
1. The preprocessor reads #include "config.h"
Because quotes are used, it first looks in the local project area, usually the directory containing main.cpp.
It finds:
project/config.h
So it includes that file.
2. The preprocessor reads #include <iostream>
Because angle brackets are used, it looks in the compiler's system include paths.
It finds the standard library header for iostream.
3. The preprocessor builds the expanded source
It effectively replaces each #include line with the contents of the matching header.
4. The compiler compiles the result
After preprocessing, the compiler sees one larger source file containing declarations from the included headers.
Simple trace example
// greeting.h
const char* message();
// main.cpp
#include "greeting.h"
#include <iostream>
const char* message() {
return "Hello";
}
int main() {
std::cout << message() << "\n";
}
Search behavior
- For
"greeting.h": local file first - For
<iostream>: system paths
Result
The program compiles because both headers are found in the expected places.
Real World Use Cases
1. Including your own modules
In a project with files like database.h, auth.h, or config.h, developers usually write:
#include "database.h"
#include "auth.h"
#include "config.h"
This makes it clear these files belong to the project.
2. Using the C or C++ standard library
#include <string>
#include <vector>
#include <map>
These are standard headers provided by the compiler toolchain.
3. Including third-party libraries
Libraries installed through the system or package manager are often included with angle brackets:
#include <openssl/ssl.h>
#include <curl/curl.h>
4. Large codebases with nested folders
A project may organize headers like this:
#include "models/user.h"
#include "services/email_service.h"
Quotes tell the preprocessor these are project headers, even if they are inside subfolders.
5. Build systems and include paths
Tools like CMake, Make, and IDEs often configure include directories. Once configured, developers can include project headers cleanly and consistently.
For example:
#include "app/settings.h"
#include <fmt/core.h>
Here:
app/settings.hmay come from your projectfmt/core.hmay come from an installed formatting library
Real Codebase Usage
In real projects, the difference is not just syntax style. It helps communicate ownership and location of headers.
Common conventions
Project headers use quotes
#include "logger.h"
#include "user_repository.h"
This signals: "these files are part of this codebase."
Standard and external headers use angle brackets
#include <vector>
#include <string>
#include <spdlog/spdlog.h>
This signals: "these files come from the toolchain or installed dependencies."
Common project patterns
1. Keep local includes separate from system includes
Many teams group includes like this:
#include <iostream>
#include <vector>
#include "config.h"
#include "parser.h"
This improves readability.
2. Avoid ambiguous header names
If your project has a file named string.h, it can conflict with system headers.
Better:
#include "app_string.h"
or place it in a folder:
#include "app/string.h"
3. Use include paths configured by the build system
Instead of writing fragile relative paths everywhere:
#include "../../include/utils.h"
teams often configure include directories and write:
#include "utils.h"
or
#include "core/utils.h"
4. Be consistent
A codebase should follow one clear rule:
- quotes for internal headers
- angle brackets for external/system headers
Consistency makes maintenance easier.
Common Mistakes
1. Using angle brackets for your own local header
Broken example:
#include <my_header.h>
This may fail if my_header.h is only in your project folder and not in the configured include paths.
Better:
#include "my_header.h"
2. Using quotes for standard library headers
This often still works if the compiler falls back to system paths, but it is not the normal convention.
Less clear:
#include "vector"
Better:
#include <vector>
3. Assuming all compilers behave exactly the same
Beginners sometimes assume the search rules are identical everywhere. In practice, compiler options and build tools can change include paths.
How to avoid this:
- follow standard conventions
- configure include directories correctly
- test builds across environments when possible
4. Naming a project header like a system header
Broken example:
#include "stdio.h"
If your project also has a local stdio.h, you may accidentally include the wrong file.
How to avoid this:
- use unique names
- place project headers in project folders
5. Using messy relative paths everywhere
Example:
#include "../../../common/helpers.h"
This is hard to maintain when folders move.
Better approaches:
- configure include directories in the build system
- use stable include paths
6. Forgetting include guards or #pragma once
Even if the right file is found, repeated inclusion can cause errors.
Example:
#ifndef CONFIG_H
#define CONFIG_H
int getPort();
#endif
Or:
#pragma once
Comparisons
| Form | Typical use | Search starts in | Common examples |
|---|---|---|---|
#include <...> | System or installed library headers | System/include paths | <iostream>, <vector>, <stdio.h> |
#include "..." | Project/local headers | Current file or local directory first, then include paths | "config.h", "user.h" |
#include <...> vs #include "..."
- Angle brackets emphasize external or system-provided headers.
- Quotes emphasize local or project-owned headers.
- In many compilers, quotes search locally first, then fall back to normal include paths.
Comparison with relative paths
| Approach | Example | Pros | Cons |
|---|---|---|---|
| Quotes with simple name | #include "config.h" | Easy to read | Depends on include path setup |
| Quotes with subfolder | #include "core/config.h" | Clear structure | Requires organized folders |
| Long relative path | #include "../../core/config.h" | Works without extra config sometimes | Hard to maintain |
Comparison with imports
Some newer languages use import rather than textual inclusion.
| Concept | C/C++ #include | Module/import systems |
|---|---|---|
| What it does | Textually includes file contents | Imports named modules or packages |
| Build impact | Can increase compile dependencies | Often more structured |
| Typical use | Headers | Modules/packages |
For beginner C and C++ code, the key thing to remember is still the header search behavior.
Cheat Sheet
Quick rule
- Use
#include "file.h"for your own headers. - Use
#include <file>or#include <file.h>for standard library and installed library headers.
Syntax
#include "my_header.h"
#include <vector>
Search behavior
Quotes
#include "my_header.h"
Usually searches:
- local/current file directory first
- then configured include directories
Angle brackets
#include <vector>
Usually searches:
- system/include directories
Good examples
#include "config.h"
#include "models/user.h"
#include <iostream>
#include <string>
Avoid
#include "vector" // unusual for standard headers
#include <config.h> // may fail for local project files
#include "../../../x.h" // hard to maintain
Important notes
- Exact search order can vary by compiler.
- Build flags can add include directories.
- Use include guards or
#pragma oncein headers. - Be consistent across the project.
FAQ
When should I use quotes in #include?
Use quotes for headers that belong to your own project, such as "config.h" or "user.h".
When should I use angle brackets in #include?
Use angle brackets for standard library headers and installed third-party library headers, such as <iostream> or <curl/curl.h>.
Do quotes and angle brackets always search completely different places?
Not always. In many compilers, quotes search the local directory first and then the normal include paths. Angle brackets usually skip the local-first step.
Can #include "file.h" still find system headers?
Often yes, if the compiler does not find a local file and then falls back to system include paths. But it is better to follow the normal convention.
Why did my local header not compile with angle brackets?
Because the compiler may only be searching system include paths for <...>, and your project directory may not be part of those paths.
Is this behavior identical in all compilers?
No. The exact rules can vary, especially with compiler options and build system settings. The common convention still applies across most environments.
What if my project header has the same name as a system header?
That can cause confusion or accidental mismatches. Use unique names or place project headers in named folders such as "app/config.h".
Does #include copy the whole file contents?
Conceptually, yes. The preprocessor replaces the #include line with the contents of the target header before compilation.
Mini Project
Description
Create a small C++ project with one local header and one standard library header to see how #include "..." and #include <...> are used together. This project demonstrates the common convention used in real programs: local project code uses quotes, while standard library code uses angle brackets.
Goal
Build and run a small program that includes a local header with quotes and a standard library header with angle brackets.
Requirements
- Create a local header file named
greeting.h. - Declare a function in
greeting.hthat returns a greeting message. - Include
greeting.hin your main source file using quotes. - Include
<iostream>in your main source file using angle brackets. - Print the greeting message to the console.
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.