Question

Difference Between #include <...> and #include "..." in C and C++

ccppincludeheader-filesc-preprocessor

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:

  1. The current file's directory, or the directory of the including file
  2. 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.

Take Quiz

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.h may come from your project
  • fmt/core.h may come from an installed formatting library
Take Quiz

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

FormTypical useSearch starts inCommon examples
#include <...>System or installed library headersSystem/include paths<iostream>, <vector>, <stdio.h>
#include "..."Project/local headersCurrent 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

ApproachExampleProsCons
Quotes with simple name#include "config.h"Easy to readDepends on include path setup
Quotes with subfolder#include "core/config.h"Clear structureRequires organized folders
Long relative path#include "../../core/config.h"Works without extra config sometimesHard to maintain

Comparison with imports

Some newer languages use import rather than textual inclusion.

ConceptC/C++ #includeModule/import systems
What it doesTextually includes file contentsImports named modules or packages
Build impactCan increase compile dependenciesOften more structured
Typical useHeadersModules/packages

For beginner C and C++ code, the key thing to remember is still the header search behavior.

Take Quiz

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:

  1. local/current file directory first
  2. then configured include directories

Angle brackets

#include <vector>

Usually searches:

  1. 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 once in 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.

Take Quiz

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.h that returns a greeting message.
  • Include greeting.h in your main source file using quotes.
  • Include <iostream> in your main source file using angle brackets.
  • Print the greeting message to the console.
Take Quiz

Keep learning

Related questions

View more