C初心者が知っておきたいヘッダーファイルとリンクの基礎知識:目指せ! Cプログラマ(終)(1/4 ページ)
プログラミング言語の基本となる「C」の正しい文法や作法を身に付ける入門連載です。今回は、ヘッダーファイルとリンクを中心に、翻訳単位、ファイル有効範囲、外部定義と仮定義、外部結合と内部結合、結合と記憶域期間、インライン関数の結合、static、extern、inlineなどについても解説。
C言語の処理を複数のファイルに分けて書くには
本入門連載「目指せ! Cプログラマー」では、これまで、C言語の初心者でも分かるようにさまざまな基本文法や基礎構文、標準ライブラリの使い方などを解説してきました。新社会人はもちろん、C言語に入門したいという方もあらためてバックナンバーを読み返してみてください。
連載もいよいよ終盤です。今回は、C言語の処理を複数のファイルに分けて書く方法について解説します。
実際の開発現場では、1つのプログラムのソースコードが1つのファイルから作られていることは、現実にはほとんどありません。ソースコードが複数のファイルで構成されるとき、別のファイルにあるオブジェクトを参照したり、関数を呼び出したりするためには、どのように書けばよいのでしょうか。今回はその方法を学びます。
Cにおけるソースファイルとヘッダーファイルと翻訳単位
Cのソースプログラムは「ソースファイル」「ヘッダーファイル」から構成されます。
実行プログラムはソースファイルが1つあれば作れますが、1つのファイルに何千行、何万行と書くよりも、ある程度のまとまりで分けて書いた方が便利です。機能単位で別々のファイルにして、それぞれのプログラムについて動作確認をしたり、コードレビューができたりした方が開発しやすいからです。
そのようにして作ったソースファイルは、コンパイル時に合わせることで、1つの実行プログラムを作ることができます。
ソースファイルは1つ以上のヘッダーを「インクルード」できます。インクルードしたヘッダーが、また別のヘッダーをインクルードしていることもあります。あるソースファイルと、そこからインクルードされるヘッダーを全て合わせたもので、コンパイルができるひとまとまりのものを「翻訳単位」と呼びます。
あらためて「ファイル有効範囲」とは
本連載第9回「Cにおける識別子の有効範囲と変数の生存期間」で説明した通り、Cの識別子には「ファイル有効範囲」というものがあります。これは、「宣言したところから翻訳単位の終了までの範囲」のことです。
「有効範囲」はとても大切なものです。有効範囲という概念が無いと、誰かが使った識別子は他のプログラマーが使えなくなってしまうからです。
例えば、ある変数「i」があったとして、この変数の有効範囲内では自由に「i」を使えて、範囲外では使えなくなることを思い出してください。この文法のおかげで、他のプログラマーが記述したソースの中で識別子「i」を使っていたとしても、自分が記述したソースで識別子「i」を使えるようになります。
識別子の有効範囲には幾つか種類があり、その1つに「ファイル有効範囲」があります。これは翻訳単位に依存していますから、これを意識して有効範囲をきちんとコントロールできるようになりましょう。
ファイル有効範囲をコントロールするには
ここからはファイル有効範囲をコントロールする方法について解説します。
まずは、Pleiadesで複数のソースファイルをコンパイルする方法を説明しましょう。
最初のスクリーンショットはソースファイルが1つ登録されている状態です。
「src」フォルダーを右クリックし、「新規」→「ソース・ファイル」と選びます。
「新規ソース・ファイル」ウィンドウでファイル名を入れてください。
「完了」ボタンを押すと、「src」フォルダーの下にファイルが追加されます。
同じように、「src」フォルダーを右クリックした時に「新規」→「ヘッダー・ファイル」を選べば、ヘッダーファイルを追加できます。コンパイルの方法は、ファイルが1つの場合でも複数の場合でも同じで、プロジェクトを右クリックし、「構成のビルド」→「全てビルド」を選択します。
コラム「インクルードとヘッダー」
前回の「プリプロセッサでプログラムの質を向上させよう」で解説した「プリプロセッサー」によるインクルードの対象はヘッダーだけではありません。別のソースファイルをインクルードすることもできます。
とはいえ、あまり目にすることもないでしょうし、特別な理由が無い限りヘッダーをインクルードしますので、「そんなこともできるのか」くらいに覚えておけばよいでしょう。
ところで、前回解説したようにプリプロセッサーによるインクルードには2種類の方法がありました。「#include <ヘッダー>」「#include "ソースファイル"」です。どちらも指定された内容で#include指令を置き換えますが、この2つの大きな違いは、「プリプロセッサーがどこからその置き換え対象を探すか」という点です。
厳密には両方とも処理系定義ですが、前者(「#include <ヘッダー>」)は「システムから提供される機能を提供するヘッダー」を想定しており、主にコンパイラーオプションや環境変数で指定されるパスを優先して探します。
それに対して後者(「#include "ソースファイル"」)は、インクルードしているソースファイルと同じパスを優先して探します。ソースファイルといっていますが、主にヘッダーファイル(.hファイル)です。そこで指定のファイルが見つからないときは、前者と同じようにコンパイラーオプションなどを参照して探します。
Copyright © ITmedia, Inc. All Rights Reserved.