みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

インクルードパスを相対パスで指定

Visual C++ 2017を使用したプロジェクト開発で、次のようなディレクトリ構造になっているとします。

root/
 └ dev/
   └ L1/
     ├ L2/
     │ ├ L3/
     │ │ └ L4/
     │ │   └ MyProj(開発用ディレクトリ)
     │ └ foo/
     │
     └ include/


プロジェクトファイルやソースファイルは全てMyProjの直下にあります。
L2と同じ階層にあるincludeディレクトリにあるtest.hをソースファイルにインクルードするために、次のような#include文を記述します。
#include "../../../include/test.h"

これで問題なくコンパイルが通ります。


次に、プロジェクトのプロパティの「追加のインクルードディレクトリ」に"../../foo"を追加します。
これは次のようなオプションと解釈されてコンパイラに渡されます。
/I"../../foo"
fooというディレクトリのみを参照パスに追加するつもりで、プロジェクトファイルからの相対パスで指定しました。


さてここで#include文を次のように書き換えてみました。
#include "../../include/test.h"

これでコンパイルが通るのです。
ソースファイルからtest.hへの相対パスは
../../../include/test.h
のはずですが、なぜこれでコンパイルが通るのでしょうか?

ちなみに「追加のインクルードディレクトリ」に何も指定しない状態では、includeファイルを開けないと出てコンパイルエラーとなります。
なのでこの設定が影響しているのだとは思いますが。

投稿日時 - 2018-03-29 18:43:17

QNo.9483057

困ってます

質問者が選んだベストアンサー

> インクルードパスに foo を追加すると、foo は相対パスをたどる時の基準点にもなると言うことでしょうか?
そういうことです。
マイクロソフト(https://docs.microsoft.com/ja-jp/cpp/build/reference/i-additional-include-directories)によれば、
以下、引用
コンパイラは、次の順序でディレクトリを検索します。
1.ソース ファイルを含むディレクトリ。
2.指定されたディレクトリ、 /I CL で出現する順序でのオプションです。
3.指定したディレクトリ、 INCLUDE環境変数。
引用終わり
とのことです。
コンパイラ(プリプロセッサ)からしてみれば、インクルード指令(#include)を読み込んだ時、上記の順番でディレクトリを検索し、ファイルが見つかればインクルード処理を行います。
この時、ファイル名が単なるファイル名だろうと、相対ファイル名だろうと同じです。

> そうすると、ある相対パスの表現が、別の階層にある複数の同名のディレクトリを指してしまうことになりませんか?
それが何か問題なのですか?
相対パスでなくとも複数の同名ファイル名がインクルードパスに現れることはあり得ますが、上記の通りディレクトリの検索順序は決まっていますので、その順に検索を行い、先に見つかったものがインクルードされます。
ソースファイルを記述する者はその検索順序を意識してインクルード指令を記述する、またはディレクトリ構成を作成する必要があります。

> 意図したのは、fooの中にあるファイルを#includeの検索パスに含めて欲しいだけなのですが。
インクルードパスとはそういうものだからしょうがないでしょうね。
逆にそうなっていなかったら、階層構造を持つライブラリを使用する時、インクルードパスを複数書く必要があって面倒。例えば
#include <sys/stat.h>

投稿日時 - 2018-03-31 08:27:59

お礼

なるほど、MSのサイトにも説明がありましたね。
インクルードパスが増えると検索の基準点も増えてしまい、特に相対パス指定の場合は直感的にどのフォルダが検索対象になっているのか把握しづらいですね。

投稿日時 - 2018-03-31 11:36:36

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.1

MyProj以下のソースファイルから見て ../../../ はL2階層なので、
L4階層が余分なのではないかと思われます。

でL4階層が余分であるとして、、、
インクルードパスに foo を追加したので、プリプロセッサは
foo から ../../にあるinclude/test.h を見つけることができ、
コンパイルは成功します。

投稿日時 - 2018-03-30 17:46:59

お礼

ご回答ありがとうございます。
仰る通りL4が余分でした。失礼しました。

で、インクルードパスに foo を追加すると、foo は相対パスをたどる時の基準点にもなると言うことでしょうか?
そうすると、ある相対パスの表現が、別の階層にある複数の同名のディレクトリを指してしまうことになりませんか?

意図したのは、fooの中にあるファイルを#includeの検索パスに含めて欲しいだけなのですが。

投稿日時 - 2018-03-30 18:37:08

あなたにオススメの質問