相対パスでのインクルードパス指定の正体とは?

このQ&Aのポイント
  • Visual C++ 2017を使用したプロジェクト開発で、相対パスを使用してインクルードパスを指定する方法について説明します。
  • プロジェクトファイルやソースファイルは開発用ディレクトリの直下にあり、その中にL2と同じ階層にあるincludeディレクトリが存在します。
  • インクルードディレクトリの指定やソースファイルからの相対パスの解釈により、コンパイルが通る理由やエラーが発生する理由についても解説します。
回答を見る
  • ベストアンサー

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

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ファイルを開けないと出てコンパイルエラーとなります。 なのでこの設定が影響しているのだとは思いますが。

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

  • ベストアンサー
回答No.2

> インクルードパスに 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>

katorea21
質問者

お礼

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

その他の回答 (1)

回答No.1

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

katorea21
質問者

お礼

ご回答ありがとうございます。 仰る通りL4が余分でした。失礼しました。 で、インクルードパスに foo を追加すると、foo は相対パスをたどる時の基準点にもなると言うことでしょうか? そうすると、ある相対パスの表現が、別の階層にある複数の同名のディレクトリを指してしまうことになりませんか? 意図したのは、fooの中にあるファイルを#includeの検索パスに含めて欲しいだけなのですが。

関連するQ&A

  • 相対パスの指定

    FindFirstFile(), remove(), OPENFILENAME などのファイルやフォルダのパスを扱うものについて、例えば 実行ファイルと同じディレクトリに有るdat.datというファイルを「dat.dat」とだけ書いて相対指定したつもりが、実行ファイルと同じディレクトリにdat.datが無かった場合にWindowsフォルダなどの特殊なフォルダや、AUTOEXEC.BATに書いてあるフォルダを使ってdat.datが検索されて適用されたりすることはあるのでしょうか? いろいろな関数や構造体が有りますが、相対パスが指定されたとき、絶対パスを作るために使用されるフォルダパスが、GetCurrentDirectory()以外のものが使われることってあるんでしょうか?

  • 絶対パスと相対パスはどちらがいい?

    htmlで自サイト内のリンクをつける場合、絶対パスと相対パスはどちらを使った方がいいのでしょうか? すべてのファイルが同じディレクトリにあるとして、 <a href="test.html">test</a> と <a href="http://example.com/test.html">test</a> では、SEOの効果が違ったりしますか? 教えて下さい。よろしくお願いいたします。

    • ベストアンサー
    • HTML
  • javascript 相対パス表示

    javascirptで、現在のページのディレクトリを取得し サイトルート相対パスで表示させるには どうしたらよいでしょうか? 例;http://testweb.co.jp/test01/test02/test.html   ↓ サイトルート相対パスでディレクトリのみを表示  /test01/test02/

  • インクルードファイルからの相対パス

    main.php: <?php include('x/sub.php'); ....... ?> x/sub.php: <?php $a=file('data.txt'); ....... ?> において data.txt は main.php と同じディレクトリになければなりません インクルードされたファイルからファイルを呼び出すときに インクルード先からの相対パスでファイルを指定できるようにできないでしょうか? つまり上の場合にはdata.txtがsub.phpと同じディレクトリにあるようにです

    • ベストアンサー
    • PHP
  • 相対パスについて

    初歩的なことですみません。 相対パスについて教えてください。 <public_html>---<cgi-bin>---<ccc>---<ttt.pl> *************| *************---<eee>---<test.html> こちらの構成で、(***は無視してください。) (public_htmlの下はcgi-binとeeeフォルダです。) test.htmlから見た、ttt.plのパスは ../cgi-bin/ccc/ttt.pl  でよいのでしょうか?? CGIを設置する時、ディレクトリを変えたら、動かなくなってしまったので・・・ 宜しくお願いします。

    • 締切済み
    • CGI
  • dllを参照追加をするときのパスについて

    VS2015で開発をしていてサードパーティ製のツールを使用しています。 そのうちのいくつかのdllをプロジェクトに参照追加しています。 端末(1)で新たにdllを参照追加しました。 端末(2)でフォルダ階層の違う場所でソリューションを開くと さきほどのプロジェクトの参照追加したdllに参照できないマークがつき、コンパイルするとワーニングが出力されます。 これはなぜでしょうか? また、以前から追加されているdllの「.csproj」内のパスは 端末(1)にはないディレクトリとなっているのですが、エラーになりません。 このプロジェクトファイル以外にもパスを管理しているものがあるのでしょうか? ご存知の方がいらしたらご教授頂きたいです。

  • includeのパス指定は"/"で始められない?

    こんにちは。php5でウェブアプリを作っています。 いろんな階層からincludeされるファイルの中にさらにincludeを記述しているため、相対パス指定ではなく、ドキュメントルートからのパスを include("/top/hoge/aaa.php"); のように書きたいのですが、こうすると読み込んでくれません。includeではこういう指定は出来ないんですか? みなさんどうなさってますでしょうか。includeファイルの中のinculdeのパスの指定…。

    • ベストアンサー
    • PHP
  • batファイルの相対パス

    batファイルの相対パス あるバッチが相対パスであるファイルを参照しています このバッチファイルを直接起動すれば、正しく参照できますが、 別のディレクトリにいる別のバッチファイルからcallされた場合、 呼び出し先の相対パスではなく、 呼び出し元の相対パスになってしまいファイルを参照できません。 この問題をスマートに解決する方法はありませんか? 例のchild.batからはfile.txtを参照できますが、 parent_1.bat経由の場合、ファイルが見つかりませんとなります。 child.bat の中で、「cd c:\dir_a」を書いて基点を変更すればとりあえずは行けそうですが、可能な限り絶対パスのベタ書きは避けたいです。 宜しくお願いします。 【例】 c:\ | +-dir_a | | | +-child.bat | | | +-file.txt | +-dir_b | | | +-parent_1.bat | +-dir_c | +-parent_2.bat ===== file.txt ===== test-test-test ===== file.txt ===== ===== child.bat ===== type ./file.txt pause ===== child.bat ===== ===== parent_1.bat ===== call c:\dir_a\child.bat ===== parent_1.bat =====

  • C言語:汎用のオブジェクトファイルのパス

    main.cで #include "fileio.h" して、関数の実体等をfileio.cに記述する場合コンパイルについてです。 fileio.hが様々なプログラムで使う関数群の場合で、/home/hoge/mylib 以下に fileio.h と fileio.o を置いたとします。また、main.cは別ディレクトリで開発しているとします。 環境変数C_INCLUDE_PATHを設定しておけばヘッダファイルは参照できました。(main.c内で#include "fileio.h" とするだけで参照できました) makeでコンパイルしたいのですが、オブジェクトファイルはMakefile中で LIBOBJS = /home/hoge/mylib/fileio.o などとフルパスで指定しなければいけないのでしょうか? ファイル入出力関数群など、汎用的な関数をまとめてmylibに置きたいので、どこかでmylibディレクトリのパスを指定して、ファイル名(fileio.o)だけで参照できるならそうしたいのですが。 また、そもそも汎用関数群はこういうディレクトリ構造で管理したほうがいい、などというアドバイスがあればお願いします。

  • GCCの#includeパスの設定方法?

    RedHat Linux 8.0をインストールしています。adaptec社のAHA1542を使いたいのですが、自動認識してくれません。 色々調べた結果、/etc/modules.confに alias scsi_hostadapter aha1542.o を記述する事で、使用可能と言う事がわかりました。 しかし私のシステムでは、aha1542のソースとヘッダーファイルはありますが、オブジェクトがありません。 GCCにてコンパイルさせたら、大量のエラーメッセージが出力されます。ソースを見ると、 1) #include <linux/******.h> 2) #include <asm/*****.h> 3) #include "*****.h" と3種類の#include文があります。 3)は、ソースと同一ディレクトリーでOKだと思いますが、他の2種類のパスの設定方法がわかりません。 <linux/ <asm/ の部分を自分のシステムに合ったパスに置き換える(GCCに認識させる)には、どうすれば良いのでしょうか? どうか、宜しくお願い致します!

専門家に質問してみよう