
C言語の基本|C言語の#includeとヘッダファイルのしくみ
いつも書いているその1行には意味がある。#includeを理解して、C言語のコンパイルの流れを見通そう
C言語のプログラムでは、ソースコードの先頭に次のような記述をよく書きます。
#include <stdio.h>printfで文字列を表示するときや、scanfで値を入力するときに、何気なく書いてきた人も多いでしょう。
しかし、#includeは単なる決まり文句ではありません。関数、型、マクロなどの情報をプログラムに取り込み、コンパイラがコードを正しく確認できるようにするための大切な仕組みです。
例えば、printfを使うときにはstdio.hをインクルードします。stdio.hには、printfがどのような形式で呼び出される関数なのかという宣言が含まれています。
この宣言があることで、コンパイラはprintfの呼び出し方を確認できます。引数の指定に問題がある場合には、警告やエラーを表示してプログラマーに知らせることができます。
また、#includeは、プログラムの実行中にライブラリを読み込む処理ではありません。コンパイルが始まる前の前処理で、指定したヘッダの内容を取り込むための前処理指令です。
この仕組みを理解すると、次のような疑問が解消されていきます。
- なぜprintfを使うときにstdio.hが必要なのか
- ヘッダファイルには何が記述されているのか
- #includeはいつ処理されるのか
- 関数の宣言と関数本体は何が違うのか
- 山かっこと二重引用符をどのように使い分けるのか
- #includeを書けば関数本体まで取り込まれるのか
ここでは、ヘッダファイルの役割、前処理の流れ、主な標準ヘッダ、山かっこと二重引用符の使い分けについて、順番に見ていきましょう。
ヘッダファイルとは
ヘッダファイルとは、関数の宣言、マクロ、型定義など、ほかのソースコードから機能を利用するために必要な情報をまとめたファイルです。
一般的なヘッダファイルの名前には、headerの頭文字を表す.hという拡張子が使われます。
代表的な標準ヘッダには、次のようなものがあります。
- stdio.h
- string.h
- ctype.h
- math.h
- stdlib.h
- time.h
例えば、printfを使うプログラムでは、次のようにstdio.hをインクルードします。
#include <stdio.h>この記述によって、stdio.hが提供するprintfなどの宣言をプログラムで利用できるようになります。
ヘッダファイルは、必要な機能を利用するための案内書や入口のような存在です。通常、標準ライブラリ関数の処理本体がそのまま書かれているのではなく、その関数をどのような形式で呼び出すのかを知らせる情報がまとめられています。
ヘッダファイルの主な役割
ヘッダファイルが提供する主な情報は、関数の宣言、マクロ、型定義の3つです。
| ヘッダファイルの役割 | 内容 | 例 |
|---|---|---|
| 関数の宣言を提供する | 関数名、引数、戻り値の型をコンパイラに知らせる | printf、strlen、sqrt |
| マクロを提供する | 定数や簡単な処理を名前で利用できるようにする | EOF |
| 型定義を提供する | 特定の機能で必要になる型を利用できるようにする | size_t、FILE |
関数の宣言を提供する
関数の宣言は、関数の名前、受け取る引数、返す値の型などをコンパイラに知らせます。関数プロトタイプと呼ばれることもあります。
例えば、文字列の長さを求めるstrlenは、string.hで宣言されています。
その宣言は、次のような形式です。
size_t strlen(const char *s);この宣言から、コンパイラは次の情報を確認できます。
- 関数名はstrlenである
- 引数として文字列の先頭を表すポインタを受け取る
- 戻り値はsize_t型である
- 引数が指している文字列を関数内で変更しない
適切な関数の宣言が見えていれば、コンパイラは関数の呼び出し方を確認しやすくなります。
マクロを提供する
ヘッダファイルには、マクロが定義されていることもあります。
マクロを利用すると、定数や簡単な処理を意味の分かる名前で表現できます。
例えば、stdio.hでは、入力の終わりや入力エラーを表す値としてEOFが提供されています。
if (ch == EOF) {
/* 入力の終わり、または入力エラー */
}EOFの具体的な数値をプログラムに直接書くのではなく、意味を表すEOFを使うことで、処理の目的が分かりやすくなります。
型定義を提供する
ヘッダファイルには、特定の機能を利用するときに必要な型が定義されていることもあります。
| 型 | 主な用途 |
|---|---|
| size_t | 配列の大きさや文字列の長さなどを表す |
| FILE | ファイルを扱うための情報を表す |
strlenの戻り値にはsize_tが使われます。また、ファイル入出力ではFILE型へのポインタを利用します。
このように、ヘッダファイルは関数の宣言だけでなく、その機能に関連する型やマクロも提供しています。
図1:ヘッダファイルが提供する3つの情報

この図から分かること
ヘッダファイルには、関数の宣言だけでなく、マクロや型定義もまとめられています。
プログラムで標準ライブラリの機能を使うには、関数名だけを知っていればよいわけではありません。引数、戻り値、関連する型などの情報も必要です。
ヘッダファイルは、これらの情報をプログラムへ提供し、コンパイラが関数の呼び出し方を確認できるようにします。
なぜヘッダファイルが必要なのか
C言語では、関数を適切に呼び出すために、その関数がどのような形式で宣言されているのかをコンパイラに知らせる必要があります。
例えば、printfは、引数として書式文字列を受け取り、その書式に応じて追加の引数を受け取る関数です。
printf("得点は%d点です。\n", score);stdio.hをインクルードすると、コンパイラはprintfの宣言を確認できます。その情報を基に、関数の呼び出し方に問題がないかを調べます。
ヘッダファイルは、プログラムを正しくコンパイルするための形式的な飾りではありません。関数の誤った使い方を見つけやすくし、安全性を高める役割があります。
ヘッダファイルを読み込まない場合の問題
必要なヘッダファイルをインクルードせずに関数を呼び出すと、次のような問題が発生します。
| 発生する問題 | 内容 |
|---|---|
| 警告やエラーが出る | 関数の宣言が見つからず、正しくコンパイルできないことがある |
| 引数を確認できない | 引数の個数や型を適切に確認できなくなる |
| 戻り値を確認できない | 関数が返す値の型を正しく判断できなくなる |
| 間違いを発見しにくい | 本来ならコンパイラが見つけられる問題を確認しにくくなる |
| 処理系による違いが出る | コンパイラやC言語規格の設定によって結果が変わる可能性がある |
現在のC言語では、関数を適切に宣言せずに呼び出すことは正しい書き方ではありません。
開発環境によっては警告だけで実行ファイルが作られる場合もあります。しかし、警告が出ても動作したから問題がないとは限りません。
関数を使うときは、その関数が宣言されているヘッダを正しくインクルードしましょう。
関数の宣言と関数本体の違い
ヘッダファイルの役割を理解するには、関数の宣言と関数本体の違いを知ることが大切です。
| 種類 | 役割 |
|---|---|
| 関数の宣言 | 関数名、引数、戻り値の型をコンパイラに知らせる |
| 関数本体 | 関数が実際に行う処理を記述する |
例えば、商品の合計金額を計算する関数の宣言は、次のように記述できます。
int calculate_total(int price, int count);この宣言から、calculate_totalは2つのint型の値を受け取り、int型の値を返す関数であることが分かります。
関数本体は、次のように記述します。
int calculate_total(int price, int count)
{
return price * count;
}関数の宣言は、関数の使い方を知らせる情報です。関数本体には、実際に実行される処理が記述されています。
ヘッダファイルには、一般的に関数の宣言を記述します。実際の処理を行う関数本体は、別のソースファイルやライブラリに用意されます。
stdio.hをインクルードしても、printfの処理本体がそのままソースコードへ書き込まれるわけではありません。stdio.hからは、printfを正しく呼び出すための宣言などが提供されます。
#include指令とは
#includeは、指定したヘッダやファイルの内容を取り込むための前処理指令です。
前処理指令は、行の先頭に#を付けて記述します。
#include <stdio.h>#includeは、C言語の関数ではありません。そのため、関数呼び出しのように丸かっこを使いません。
次の書き方は誤りです。
#include(<stdio.h>)また、#includeの行末にはセミコロンを付けません。
正しい書き方は次のとおりです。
#include <stdio.h>次のようにセミコロンを付ける必要はありません。
#include <stdio.h>;前処理とは
前処理とは、コンパイラがC言語のソースコードを本格的に解析する前に行う処理です。
前処理では、#includeなどの前処理指令が処理されます。
ソースファイルに次の記述があるとします。
#include <stdio.h>前処理では、この位置にstdio.hが提供する内容を取り込んだ状態を作り、その結果をコンパイラへ渡します。
処理の流れは次のように考えると分かりやすいでしょう。
ソースファイルに#includeを書く
↓
前処理でヘッダの内容を取り込む
↓
必要な宣言や型を含んだ状態にする
↓
コンパイラがソースコードを解析する標準ヘッダは、必ずしもstdio.hという名前の物理的なファイルとして保存されているとは限りません。C言語の処理系が、標準ヘッダとして必要な情報を提供します。
学習の初めは、stdio.hを指定すると、標準入出力に必要な情報が前処理で利用できるようになると考えておけばよいでしょう。
#includeは実行時の処理ではない
#includeについて特に重要なのは、プログラムの実行中にヘッダファイルを読み込む処理ではないという点です。
#includeは、コンパイル前の前処理で働きます。そのため、完成したプログラムを実行するたびにstdio.hを読み込んでいるわけではありません。
| 処理 | 実行される時期 | 役割 |
|---|---|---|
| #include | コンパイルより前 | ヘッダの内容を取り込む |
| printf | プログラムの実行中 | 文字列や数値を出力する |
#includeとprintfでは、働く時期も役割も異なります。
- #includeはプログラムを作る準備として働く
- printfは完成したプログラムの実行中に働く
- #includeは前処理指令である
- printfは標準ライブラリ関数である
この違いを押さえると、#includeが関数ではなく、前処理の段階で扱われる指令であることを理解しやすくなります。
前処理から実行ファイルができるまで
C言語のソースファイルから実行ファイルが作られるまでには、いくつかの段階があります。
| 段階 | 主な処理 |
|---|---|
| 前処理 | #includeなどの前処理指令を処理する |
| コンパイル | C言語のソースコードを解析して変換する |
| アセンブル | アセンブリコードからオブジェクトファイルを作る |
| リンク | オブジェクトファイルと必要なライブラリを結びつける |
開発環境によっては、これらの処理全体を広い意味でコンパイルと呼ぶこともあります。
図2:前処理から実行ファイルまでの流れ

この図から分かること
#includeは、ビルド工程の最初に行われる前処理で扱われます。ヘッダの情報を取り込んだ結果がコンパイルされ、オブジェクトファイルが作られます。
その後、リンクによってオブジェクトファイルと必要なライブラリが結びつき、実行ファイルが完成します。
ヘッダファイルが提供する宣言と、ライブラリが提供する関数本体は役割が異なります。#includeによって宣言などの情報を取り込み、リンクによって実際の関数本体と結びつくという流れです。
printfを使ったプログラムで確認しよう
ここでは、stdio.hをインクルードし、printfで学習メッセージを表示するプログラムを確認します。
stdio.hを読み込んでメッセージを表示するプログラム
ファイル名:12_2_1.c
#include <stdio.h>
int main(void)
{
/* 前処理の学習開始を表示する */
printf("#includeのしくみを確認しましょう。\n");
return 0;
}実行結果の例
#includeのしくみを確認しましょう。プログラムの詳しい解説
stdio.hをインクルードする部分
#include <stdio.h>このプログラムではprintfを使うため、printfが宣言されているstdio.hをインクルードしています。
#から始まっているため、通常のC言語の文ではなく前処理指令です。また、行末にセミコロンは付けません。
前処理が行われると、stdio.hから提供されるprintfの宣言などを利用できる状態になります。その結果、コンパイラはprintfの呼び出し方を確認できます。
main関数を定義する部分
int main(void)mainは、プログラムの実行が始まる関数です。
intは、mainがint型の値を返すことを表します。voidは、このmainが引数を受け取らない形式であることを示します。
printfでメッセージを表示する部分
printf("#includeのしくみを確認しましょう。\n");printfは、指定した書式に従って文字列や値を出力する標準ライブラリ関数です。
この例では、二重引用符で囲まれた文字列を画面に表示します。文字列の末尾にある\nは改行を表します。
printfは関数なので、呼び出しの行末にはセミコロンが必要です。
#includeとprintfの違いを整理すると、次のようになります。
| 記述 | 種類 | セミコロン | 働く時期 |
|---|---|---|---|
| #includeとstdio.hの指定 | 前処理指令 | 付けない | コンパイル前 |
| printfの呼び出し | 関数呼び出し | 付ける | プログラムの実行中 |
プログラムを終了する部分
return 0;return 0によってmain関数を終了し、プログラムが正常に終了したことを実行環境へ伝えます。
stdio.hをインクルードしなかった場合
プログラムから次の行を取り除いたとします。
#include <stdio.h>すると、printfを呼び出しているにもかかわらず、printfの適切な宣言が見つからない状態になります。
コンパイラはprintfの名前を見つけても、正しい呼び出し方を確認できません。そのため、関数が宣言されていないことを示す警告やエラーが発生します。
コンパイラによって表示内容は異なりますが、主に次のような問題が指摘されます。
- printfの宣言が見つからない
- printfが暗黙的に宣言されている
- stdio.hをインクルードする必要がある
- 組み込み関数の宣言と一致していない
警告だけで実行ファイルが作られる場合でも、ヘッダファイルを省略してよいわけではありません。printfを使う場合は、stdio.hを正しくインクルードしましょう。
主な標準ヘッダ
C言語には、目的ごとに標準ヘッダが用意されています。
| 標準ヘッダ | 主な内容 | 関数の例 |
|---|---|---|
| stdio.h | 標準入出力やファイル入出力 | printf、scanf、puts、fgets |
| string.h | 文字列やメモリの操作 | strlen、strcpy、strcmp |
| ctype.h | 文字の判定や変換 | isalpha、isdigit、toupper |
| math.h | 数学計算 | sqrt、pow、sin |
| stdlib.h | メモリ管理、数値変換、乱数など | malloc、free、rand |
| time.h | 日付や時刻の処理 | time、clock、strftime |
stdio.h
stdio.hは、標準入出力やファイル入出力に関する機能を提供します。
#include <stdio.h>主な関数は次のとおりです。
- printf
- scanf
- puts
- fgets
- fopen
- fclose
画面への出力、キーボードからの入力、ファイルの読み書きなどで使用します。
string.h
string.hは、文字列やメモリを操作する関数の宣言を提供します。
#include <string.h>主な関数は次のとおりです。
- strlen
- strcpy
- strcmp
- strcat
- strchr
C言語では文字列をchar型の配列として扱うため、string.hの関数が多くの場面で役立ちます。
ctype.h
ctype.hは、文字の種類を判定したり、英字の大文字と小文字を変換したりする関数の宣言を提供します。
#include <ctype.h>主な関数は次のとおりです。
- isalpha
- isdigit
- isspace
- toupper
- tolower
入力された文字が数字かどうかを確認したい場合や、英字の表記を統一したい場合に利用します。
math.h
math.hは、数学計算を行う関数の宣言を提供します。
#include <math.h>主な関数は次のとおりです。
- sqrt
- pow
- sin
- cos
開発環境によっては、math.hの関数を使うプログラムをビルドするときに、数学ライブラリをリンクする指定が必要になる場合があります。
stdlib.h
stdlib.hは、さまざまな汎用機能に関する宣言や型を提供します。
#include <stdlib.h>主な関数は次のとおりです。
- malloc
- free
- rand
- srand
- strtol
動的メモリ、擬似乱数、文字列から数値への変換など、幅広い処理で使用します。
time.h
time.hは、時刻や処理時間を扱う機能を提供します。
#include <time.h>主な関数は次のとおりです。
- time
- clock
- difftime
- strftime
現在時刻の取得や処理時間の測定などに利用します。
使用する機能とヘッダの関係
関数を使うときは、その関数がどの標準ヘッダで宣言されているのかを確認します。
| やりたいこと | 使用する関数 | インクルードするヘッダ |
|---|---|---|
| 書式を指定して出力する | printf | stdio.h |
| 文字列の長さを調べる | strlen | string.h |
| 数字文字か判定する | isdigit | ctype.h |
| 平方根を求める | sqrt | math.h |
| メモリを動的に確保する | malloc | stdlib.h |
| 現在時刻を取得する | time | time.h |
最初からすべての標準ヘッダを暗記する必要はありません。
関数を使うたびに、次の3つを組み合わせて確認すると覚えやすくなります。
- 何を行いたいのか
- どの関数を使うのか
- どのヘッダをインクルードするのか
例えば、文字列の長さを調べたい場合は、次のように考えます。
文字列の長さを調べたい
↓
strlenを使う
↓
string.hをインクルードする山かっこと二重引用符の違い
#includeには、主に2つの書き方があります。
#include <ヘッダ名>
#include "ファイル名"どちらも指定したヘッダやファイルを取り込む書き方ですが、主な用途と検索方法が異なります。
山かっこを使う場合
山かっこを使う形式は、主に標準ヘッダをインクルードするときに使用します。
#include <stdio.h>
#include <stdlib.h>この形式では、処理系が定めた標準的な検索場所からヘッダを探します。
stdio.hやstdlib.hなど、C言語の処理系が提供する標準ヘッダには、基本的に山かっこを使います。
二重引用符を使う場合
二重引用符を使う形式は、主に自分で作成したヘッダファイルをインクルードするときに使用します。
#include "myfunc.h"この形式では、処理系が定めた方法によってファイルを検索します。一般的には、ソースファイルに近い場所や、ユーザーが指定した検索場所などを先に調べます。
目的のファイルが見つからなかった場合は、山かっこの形式と同様の場所を検索する処理系もあります。
具体的な検索順序は、コンパイラや開発環境によって異なる場合があります。基本的には、標準ヘッダには山かっこ、自作ヘッダには二重引用符を使用すると覚えておきましょう。
2つの書き方の比較
| 書き方 | 主な用途 | 検索方法の考え方 |
|---|---|---|
| 山かっこを使う形式 | 標準ヘッダ | 処理系が定めた標準的な場所から探す |
| 二重引用符を使う形式 | 自作ヘッダファイル | ソースファイルに近い場所などを優先して探すことが多い |
この使い分けには、単に見た目を整える以上の意味があります。
標準ヘッダに二重引用符を使うと、環境によっては同じ名前の自作ファイルが先に見つかり、本来とは異なるヘッダが取り込まれる可能性があります。
反対に、自作ヘッダへ山かっこを使うと、検索場所の設定によっては目的のファイルを見つけられないことがあります。
目的に応じて適切な形式を使うことで、どのヘッダを取り込みたいのかが明確になります。
図3:標準ヘッダと自作ヘッダの検索方法

この図から分かること
山かっこと二重引用符では、ヘッダを探すときの考え方が異なります。
山かっこは、stdio.hなどの標準ヘッダに使用します。二重引用符は、myfunc.hなど、自分で作成したヘッダファイルに使用します。
この使い分けによって、処理系がどこからヘッダを探せばよいのかを伝えられます。また、ソースコードを読む人にも、標準ヘッダなのか、自作ヘッダなのかが分かりやすくなります。
自作ヘッダファイルを使う場面
学習の初めは、stdio.hやstring.hなどの標準ヘッダを利用することが中心です。
プログラムが大きくなると、自分で作成した関数を複数のソースファイルから使いたい場面が出てきます。そのようなときは、関数の宣言を自作ヘッダファイルにまとめます。
例えば、計算に関する関数をまとめたmyfunc.hがある場合は、次のようにインクルードします。
#include "myfunc.h"myfunc.hには、関数の宣言などを記述します。
int calculate_total(int price, int count);実際の関数本体は、別のソースファイルに記述します。
int calculate_total(int price, int count)
{
return price * count;
}ファイルごとの役割は、次のように分けられます。
| ファイル | 主な役割 |
|---|---|
| myfunc.h | 関数の宣言などを記述する |
| myfunc.c | 関数本体を記述する |
| main.c | 関数を呼び出して利用する |
自作ヘッダを使う詳しい方法は、複数ファイルに分割したプログラムを学ぶときに扱います。
ここでは、標準ヘッダだけでなく、自分で作成したヘッダファイルも#includeで取り込めることを押さえておきましょう。
#includeだけで関数本体が用意されるわけではない
#includeは、ヘッダが提供する宣言や型などの情報を取り込む前処理指令です。関数の処理本体まで、すべて#includeによって用意されるわけではありません。
標準ライブラリ関数を使う流れは、次のように整理できます。
ヘッダをインクルードする
↓
関数の宣言などが利用できる
↓
コンパイラが呼び出し方を確認する
↓
リンクでライブラリの関数本体と結びつく
↓
実行ファイルが完成する例えば、stdio.hをインクルードすると、printfを正しく呼び出すための情報が提供されます。その後、リンクによってprintfの実際の処理とプログラムが結びつきます。
ヘッダとライブラリの役割は、次のように分けられます。
- ヘッダは関数の使い方を知らせる
- ライブラリは関数の実際の処理を提供する
- 前処理ではヘッダの情報を取り込む
- リンクでは関数本体とプログラムを結びつける
この区別が分かると、#includeだけでなく、コンパイルやリンクの意味も理解しやすくなります。
学習するときに意識したいこと
#includeとヘッダファイルを学ぶときは、次の3点をつなげて考えることが大切です。
| 学習する項目 | 意識したいこと |
|---|---|
| #includeの意味 | コンパイル前の前処理でヘッダの内容を取り込む |
| ヘッダファイルの役割 | 関数の宣言、マクロ、型定義などを提供する |
| 形式の使い分け | 標準ヘッダには山かっこ、自作ヘッダには二重引用符を使う |
プログラムで関数を使うときは、次の順番で確認するとよいでしょう。
- 使いたい関数を確認する
- その関数が宣言されているヘッダを調べる
- ソースファイルの先頭付近でヘッダをインクルードする
- 標準ヘッダか自作ヘッダかによって形式を使い分ける
- コンパイラが表示する警告やエラーを確認する
例えば、文字列の長さを求める場合は、strlenを使います。strlenはstring.hで宣言されているため、プログラムの先頭付近でstring.hをインクルードします。
#include <string.h>このように、使用する関数と必要なヘッダを組み合わせて覚えると、適切なヘッダを選びやすくなります。
#includeは、ただソースコードの先頭に書く決まり文句ではありません。前処理で必要な情報を取り込み、その後のコンパイルで関数の呼び出し方を確認できるようにする重要な仕組みです。
標準ライブラリ関数を学ぶときには、関数の名前や使い方だけでなく、どのヘッダで宣言されているのかも一緒に確認していきましょう。
