よくよく考えてみると真面目にC言語でヘッダの書き方を解説している
書籍ってないなと感じました。
かなり重要な部分なのに、ちゃんと知らない人が多い(自分も含めて)ので、
メモ書きとして残しておきます。
ただし、自分でCを書くことはもうないと思います…。
C++使うし…その場合は必要のないテクニックだし。
ということでC言語におけるヘッダの書き方です。
一応ヘッダの書き方は大きく2つ流儀があると思うのですが、
一つはグローバル変数や共通関数をある程度大きなくくりで
どかっとまとめたものを作るタイプ、
もう一つはヘッダ(.h)のファイルと実装(.c)を分ける流儀です。
現実にはこの中間というようなのもあると思います。
今回はこの中間みたいな形式を想定して書きます。
解説はソースにまとめます。
気を付ける点を箇条書きします。ただし下記の事項はものによっては
必ずしも必須でなかったりします。
気を付ける点
・ヘッダは必ずインクルードガードする。
・グローバル変数が衝突しない工夫をする*1。
・個々の実装のヘッダには必要な情報のみ記述する。
・staticな関数は通常.cのほうに記述する。
逆に.cの内部のみで使うものは全てstaticを付ける。
・構造体も内部で使うものは.cに定義を書く。
他にもありますがそれは参考のリンクに任せることとします。
ソースコード
おまけ(Makefile)
# Makefile PROGRAM = main.exe OBJS = main.o a.o CC = gcc CFLAGS = -Wall -O4 # suffix rule .SUFIXES: .c .o # primary target $(PROGRAM): $(OBJS) $(CC) -o $(PROGRAM) $^ .c.o: $(CC) -c $< .PHONY: clean clean: $(RM) $(PROGRAM) $(OBJS)
Makefileの書き方完全に忘れた。
all書いてないし……。
こうしてみるとC++と違った意味でC言語ってやっぱり難しいよなぁと思います。
あれ?Cって宣言でstatic付けた場合は実装部にstaticってつける必要あったんでしたっけ?
C++はクラスのメンバ関数の実装につけたらエラーになった気がしています。
検証してみたらやっぱりそうだった。
#include <iostream> using namespace std; class Hoge { public: static void hogeFunc(); }; // staticをつけると…… // エラー: // cannot declare member function ‘static void Hoge::hogeFunc()’ // to have static linkage [-fpermissive] // static void Hoge::hogeFunc() // ^ void Hoge::hogeFunc() { cout << "hoge" << endl; } int main() { Hoge::hogeFunc(); return 0; }
Cの普通の関数(もちろんC++のメンバでない関数)はつけてもつけなくてもコンパイル&リンクは通る……んんん?どっちでもいいのか?そもそもプロトタイプ宣言はCでは必須ではないですし。
参考
C 言語に於けるグローバル変数の定義方法 - Qiita
C言語の正しいヘッダファイルの書き方 - saito’s blog
Makefile の書き方 (C 言語) — WTOPIA v1.0 documentation
*1:SolarisのCCだとextern宣言しなくても同じシンボルの外部変数はコモンセグメントに1つだけ作成してうまくいく