C言語のファイル分割をしてヘッダファイルの記述方法がようやく理解できた。

2018年5月25日

C言語 テクノロジー プログラミング

C言語をコーディングしてコンパイルして便利にツールを構築するのは、個人的に非常に楽しいのですが、C++がある為すでにオワコンとなりつつあるC言語ですが、個人的にシンプル構成であるC言語がたまらなく好きなんですよね。 しかし僕は簡単なツールはコーディングするんですが、アプリケーションレベルのプログラムングをC言語でやったことがありません。 iPhone開発をObjective-Cでやることはあるんですが、IDEがしっかりしているので、セオリー通りにれば、ほぼGUIでコーディングもできてしまいますので、C言語のプログラミングとは少し分けて考えなければいけませんね。 そして、Objective-Cでも、扱っている".h"という拡張子がヘッダファイルという事はわかっていたんですが、どういう役割をするのか理解できていませんでした。 今回はようやくその意味と使い方が理解できるようになったので、使い方をまとめておきたいと思います。

.hファイルの意味

ヘッダファイルという言葉から想像できる通り、.cファイルのヘッダ的な意味なのだそうです。 C言語は、オブジェクト思考が薄い言語としてC++に流れていきがちなんですが、十分にアプリケーションを作れる優れた言語でもあります。 しかし、オブジェクティブな書き方ができないと、どうしてもコードが長くなりがちです。 それを補うために、1つの大きなソースコード(.cファイル)を関数ごとにファイル分割する事で、コンパイルエラーなどの際に修正ポイントを明確にすることができます。 ヘッダファイルはそうした関数コードの宣言部分などを取りまとめてくれる役割でもあるんですね。 ここには特に深く覚えなくてはいけないことはないのですが、このヘッダファイルの使い方をインターネットで調べてみると、書き方の解説が複数存在していて、初心者がみると混乱してしまう要素が満載でした。 もちろん、C言語を深く理解して、書き方を熟知すればいいだけの話なんですが、ここはひとつ、ようやく理解できたので、ヘッダファイルの使い方パターンを解説しておきたいと思います。

ヘッダファイルの使い方といくつかのパターン

基本ソース

今回取り扱う「基本プログラム」を用意しました。 #include <stdio.h> int func1(int a , int b); int main(void){ int c = func1(11 , 22); printf("%d\n" , c); return 0; } int func1(int a , int b){ return a + b; } 実行方法 $ gcc single.c -o single.cc $ ./single.cc 33 関数に渡した"11"と"12"という数字を足し算する簡単な関数ですが、この関数部分をファイル分割してみたいと思います。

パターン1

一番簡易な使い方は、1つのC言語の関数を別ファイルに外だしして見ましょう。 #include <stdio.h> #include "lib1.h" int main(void){ int c = func1(11 , 22); printf("%d\n" , c); return 0; } #include <stdio.h> int func1(int a , int b); int func1(int a , int b){ return a + b; } $ gcc dev1.c -o dev1.cc $ ./dev1.cc 33 同じ結果が表示されたかと思いますが、これは、ヘッダファイルに関数も全て書き込んだやり方で一番簡易な方法です。 ヘッダファイルとCソースファイルが厳密に言うときちんと分けて使われていないので、仕事などで使うにはかなり荒っぽいやり方ですが、仕様としてできる事を理解していれば、簡単な構築に役立ちます。

パターン2

次は、.cファイルにも分割してみましょう。 #include <stdio.h> #include "lib2.h" int main(void){ int c = func1(11 , 22); printf("%d\n" , c); return 0; } int func1(int a , int b); #include <stdio.h> #include "lib2.h" int func1(int a , int b){ return a + b; } $ gcc dev2.c lib2.c -o dev2.cc $ ./dev2.cc 33 ヘッダファイルから#include記述が無くなっていますが、宣言部分だけを書けばいいだけなんですね。 includeは.cファイルに書きましょう。 ここで注意するポイントは、.cファイルは一緒にコンパイルしてあげないといけないと言う事です。 この辺が理解できるとC言語が「かわいいな〜」と感じる様になるのではないでしょうか?(僕だけ?)

パターン3

ヘッダファイルを厳密に書いてみる。 #include <stdio.h> #include "lib3.h" int main(void){ int c = func1(11 , 22); printf("%d\n" , c); return 0; } #ifndef LIB3_H #define LIB3_H int func1(int a , int b); #endif #include <stdio.h> #include "lib3.h" int func1(int a , int b){ return a + b; } なにやらヘッダファイルに意味不明な記述が加わりましたが、これは空間名だと考えてください。 下記の構文どおり書けば良いだけなので、おまじないとして使いましょう。 ちなみに、空間名は、大英字と数字とアンダースコアのみ使いましょう。 #ifndef 空間名 #define 空間名 〜ここに宣言記述をする〜 #endif 多言語の様な柔軟な空間名にはなりませんが、この辺まで理解しておけば、他人の書いたソースコードを読める様になるでしょう。

余談

今回のヘッダファイルに伴って、基本となるdev2.cやdev3.cに関しても、宣言部分がある場合は(今回はありませんが).hファイルに分割してみることもできます。 C言語って実行スピードが早いので、現在インタプリタで行なっているツールやアプリを簡易なものであれば、コンパイルしてツールかしておいてサーバーに設置しておくと、処理速度が早くなると思いますから、覚えておくと仕事でも便利に使えますよね。 もうひとつのメリットとしては、インタプリタと違ってコードのブラックボックス化ができるので、JSの難読化などのような仕掛けはいらなくなりますね。 ※ブラウザアプリの場合は、JSでやらないといけないので、サーバーサイドだけの処理に限られますが・・・ macやlinux環境であれば、簡単にコンパイルして実行して協力なアプリケーションを構築することも可能なC言語、こうした環境構築をきちんと覚える事でより使いやすくなりました。

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。