新人技術者のためのロジカル・シンキング入門(5) ―― ソース・コード規約の作り方
【2】どのように秩序立てればよいのか?(1/2)
さて,これらを秩序立てて分類するためには,どのようにすればよいでしょうか.defineやtypedefなどは,要するに記述が秩序立てて行われていればよいのです.define用,typedef用については,以下のような方法が考えられます.
1) 専用のヘッダ・ファイルにそれぞれ定義する
2) 記述の順番を決めて,すべての定義を一つのヘッダにまとめる
1)はもっとも簡単な方法ですが,バラバラに記述されるのが混乱のもとなので,それを避けるためにdefineやtypedefを別のヘッダ・ファイルに分けない2)のような方法も採用できます.
1)または2)のいずれかを採用すれば,定義箇所がバラバラに散乱することは防げそうです.
● 領域を使うか否かで管理は異なる
「だが,ちょっと待てよ」と,Dさんはさらに考えます.「defineならともかく,テーブルなどはどうしよう?」.
なぜなら,テーブルは領域を持っているため,領域を持たない単なる型宣言とは分けて考えなければならないはずだからです.ヘッダ・ファイルを使ってテーブルの管理方針を考える場合,どのような方針が考えられるのでしょう.
「外部変数」や「テーブル」などは,変数であるため領域を持ちます(図6).一方,defineなどはプリプロセッサが置き換えるだけのものであるため,それそのものが領域を持つわけではありません.
図6 「領域を持つ,持たない」で管理方針を分ける
ヘッダ・ファイルで定義を整理する場合,領域を持つものと持たないものは管理方法を分ける必要がある.なぜなら,前者はヘッダ・ファイルそのものに領域を確保してしまうと,ヘッダ・ファイルを複数のファイルでインクルードできなくなるから.
defineなどは領域を持たないので,ヘッダ・ファイルにおいても何の問題もありません.しかし,テーブルなどは領域を持つため,無秩序にヘッダに集めてしまうと多重定義が発生してリンク時にエラーを引き起こしてしまうことになります.
その一つの解決方法として,
- 外部変数やテーブルは,それらを定義するためのソース・ファイルを用意して,実体はそこに集めてしまうというものがあります.そして,
- ヘッダ・ファイルにextern宣言を用意し,テーブルや外部変数が必要なファイルはそのヘッダ・ファイルをインクルードする
ようにします.これらを方針として定めれば,テーブルや外部変数の参照が必要なファイルからのみアクセスできるようになります(図7).
図7 ヘッダに領域を持たない解決策
一つの解決策として,領域を持つものの場合,領域の実体をCソース・ファイルにまとめて定義してしまう.そこへの参照宣言はヘッダ・ファイルにまとめる.