.cファイルをインクルードしちゃいけない理由
小川氏の疑問に(上から目線で)答えます。
「何のこっちゃ」って人はまず http://ogawa-sankinkoutai.seesaa.net/article/125213376.html を見てください。
私の予想
「.hファイルには宣言を書き.cファイルには定義を書く」という暗黙の了解と「宣言は(矛盾しない限り)複数記述してもいいが定義は単数で無ければいけない」というルールが影響していると思います。
どういう事さ?
例えば、 hoge.c というファイルで
void hoge_func() { /* 適当にアレする */ }
と関数を定義している場合、おそらく hoge.h というファイルでは
void hoge_func();
と宣言されていると思います。
そして foo.c で
#include "hoge.h" void foo_func() { hoge_func(); } #include "hoge.c"
と記述されている。ここまでが小川氏が書いた話。(1行目のインクルードは俺の想像ですが)
ここまではコンパイルもリンクも通ります。
ところが bar.c で
#include "hoge.h" void bar_func() { hoge_func(); } #include "hoge.c"
とするとエラーになると思います。
おそらくコンパイルエラーではなくリンクエラーです。
コレは先述の「定義は単数でなければならない」というルールに反するのです。
もそっと詳しく書くと、関数 void hoge_func() はファイル foo.c とファイル bar.c の二箇所に存在するのです。
なぜ件のソースコードはコンパイルやリンクが通ったか
おそらく件の ***_main.c にある *** はモジュール名が入ると思います。
自分の経験から察するにモジュールはミニゲームかメニュー画面のようなものだと察します。
*** に入るのは minigame_00 とか menu_map_select だと思います。
さらにインクルードされるファイルに記述されている関数に
void minigame_00_input() { /* 入力処理 */ }
のようにモジュール名を関数名に含めるようなコーディングルールが設定されていたのではないかと思います。(これらの関数はモジュール内での参照にとどまるのが前提です)
そうすると結果的に関数名の衝突が起こりません。
件の会社はこの辺の事情を知っていたのか
余計なお世話にも聞こえるかも知れませんが、こういうことが気になるものです。
推測を元に書きましたが、このコーディングスタイルは"モジュール名を関数名に含める"というコーディングルールがあるから成立しています。
ミニゲーム集を作っていたり似たようなメニュー群を作っていたりすると、「予め出来上がったファイルをコピーして新しいファイルの雛形とする」っていう事をよくやります。
例えば minigame_00.c を minigame_01.c という名前でコピーして新しいファイルにします。そのときに minigame_01.c の中の関数もリネームするのですが、うっかりリネームに漏れがあったりするとやはり隣家エラーが起きます。アホみたいな話ですが、1個だけ mini_game_00_*** なんてシンボルになっていたりして置換できなかったなんて事があるんです。
こんな置換漏れがあっても(モジュール内の参照にとどまるシンボルに限りますが)リンクエラーが起きない記述方法があります。
それには下記のように static をつけます。
static void hoge_func() { /* 適当にアレする */ }
こうすると hoge_func はコンパイル単位にスコープが限定されるので名前の衝突が起きません。
こんな感じで static 宣言されているならこの辺の事情を知っていると思ってもいいと思います。