オプション沼(12) 外部からヘッダ・ファイルを与えられる -include オプション

Joseph Halfmoon

コマンドライン・オプションと言っても、よく使うやつもあれば、使い方がわからないやつもあります。中には使い方は分かるけれども、使うべき局面に遭遇したことがないやつもあり。この老人の場合、gccの-includeオプションはそんなオプションであります。外部からヘッダファイルを読み込ませるもの。何時使うの?いまでしょ?

※『オプション沼』投稿順indexはこちら

※動作確認に Windows11 WSL2上のUbuntu 20.04 LTS を使用しています。gccのバージョンは9.4.0です

gccにパスやファイルを指定するオプションは大忙しだが…

リンクするライブラリを指定する -l オプション、インクルードパスを追加指定する -I オプション、ライブラリパスを追加する -L オプションなどは、ちょいと複雑なビルド用のスクリプトには大量に含まれておりますな。自分で書くかどうかは別にして結構お馴染みのもの。しかし、その中にあって、

-include チョメチョメ

は、やってくれることは明らかなのでありますが、使うべき局面に遭遇したことがないのであります。だって、ソースコードに

#include “チョメチョメ”

と書きこむのと一緒だもの。必要なヘッダファイルがあるのならソースコード中に明示しておく方が良いと思うし。コマンドラインから与えるというのは後で無用の混乱を引き起こしそうだと(老人の忘却力では。)まあ、ソースを1行でも改変するのが憚られる場合くらいしか思いつかんぞなもし。

なお、コマンドラインで -include したファイルは、ソース中の#includeより先に処理されるみたいです。よってソースの中の定義を上書きするような使い方は出来そうにないです。また、複数の-includeファイルがあれば、順番どおりだとか。

実験

前回使用した意味なしソースを「改造」して -include の御利益を味わう実験を計画いたしました。missingInclude

 

上記の赤線位置には、別のcソースファイル中で定義されている getMessage()関数のプロトタイプが含まれるヘッダファイルの #include 文があったのであります。1行消してしまいました。

これをそのままビルドするとこんな感じ。no_include_warning

 

上記のように、warningが2件出力されてしまいましたが、フェイタルなエラーではないです。それが証拠にオプジェクトファイルである a.out も生成されとりますがな。

実行結果が以下に。セグメンテーション・フォルトだあ。SegmentationFault

この結果を反省すると次のごとし。知らんけど。

    1. コンパイラは main関数のコンパイル時に getMessage関数の呼び出しを見つけるが、プロトタイプ宣言が無いので implicitな宣言(戻値はint型、警告のみ発する)ということでコンパイルはしておく
    2. そうすると char * と宣言した変数に int 型をキャスト無に代入することになるけれども「寛容な」Cコンパイラは警告のみでコンパイルは通してくれる。
    3. リンカは別ファイルのオブジェクトファイルにgetMessage関数を見つけることができるので、mainとgetMessageのリンクは行って、実行ファイルを生成してくれる
    4. 実行するとポインタ(64ビット環境なので64ビット幅の筈)とint型(多分32ビット幅)のミスマッチのあるコードを実行することになりセグメンテーション・フォルトが発生。

やっぱり、プロトタイプ宣言を削ってしまったためでありますな。そこで外部から -include sub.h なるヘッダファイルのインクルートを指定してやりました。

$ gcc -include sub.h -g -O0 main.c sub.c

実行結果が以下に。
ExecOK

警告もなくビルド成功、問題なく動いております。しかし -include 何に使いますかな?

オプション沼(11) Makefileの友? それほどでもない? gcc の-Mオプション へ戻る

オプション沼(13) コードカバレッジを計測する準備、gcc –coverageオプション へ進む