1,980


503

#include <ファイル名>と#include "ファイル名"の違いは何ですか?

CおよびCプログラミング言語では、次のように山括弧を使用することと `include`ステートメントで引用符を使用することの違いは何ですか?

  1. #include

  2. #include" filename "

31 Answer


1,152


実際には、違いはプリプロセッサがインクルードファイルを検索する場所です。

`#include`の場合、プリプロセッサは通常コンパイラ/ IDEによって指定された検索ディレクトリで、実装依存の方法で検索します。 このメソッドは通常、標準のライブラリヘッダファイルをインクルードするために使用されます。

`#include" filename "`の場合、プリプロセッサは最初にディレクティブを含むファイルと同じディレクトリを検索し、それから `#include`フォームに使用される検索パスをたどります。 このメソッドは通常、プログラマ定義のヘッダファイルをインクルードするために使用されます。

より完全な説明はGCC https://gcc.gnu.org/onlinedocs/cpp/Search-Path.html [検索パスに関する文書化]にあります。


627


知る唯一の方法は、実装のドキュメントを読むことです。

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=182 [the C standard]、セクション6.10.2、段落2から4には次のように記載されています。

_ _ * 次の形式の前処理指令

+

#include  new-line

`<`と `>`デリミタの間の指定されたシーケンスによって一意的に識別される* header のために実装定義の場所のシーケンスを検索し、 header *の内容全体でそのディレクティブを置き換えます。 場所の指定方法または識別されたヘッダーの実装方法は実装によって異なります。 * 次の形式の前処理指令

+

#include "q-char-sequence" new-line

`" `区切り文字の間の指定されたシーケンスによって識別される*ソースファイル*の内容全体でその指令を置き換えます。 名前付き* sourceファイル*は、実装定義の方法で検索されます。 この検索がサポートされていない場合、または検索が失敗した場合、ディレクティブは読み取りのように再処理されます。

#include  new-line

元のディレクティブからの同一の含まれたシーケンス(もしあれば `>`文字を含む)。 * 次の形式の前処理指令

+

#include pp-tokens new-line

(これは、前の2つの形式のいずれとも一致しません)許可されています。 ディレクティブの `include`の後の前処理トークンは通常のテキストと同じように処理されます。 (現在マクロ名として定義されている各識別子は、その前処理トークンの置き換えリストに置き換えられます。)すべての置き換えの後に生成される指令は、前の2つの形式のうちの1つと一致します。 `<`と `>`の前処理トークンのペアまたは `" `の文字のペアの間の一連の前処理トークンを単一のヘッダ名前処理トークンに結合する方法は実装定義です。

定義:

  • h-char:改行を除くソース文字セットのメンバー 文字と >

  • q-char:改行を除くソース文字セットのメンバー 文字と `" ` _ _


244


<と>の間の文字のシーケンスは一意的にヘッダーを参照します。ヘッダーは必ずしもファイルではありません。 実装では、必要に応じて文字シーケンスを自由に使用できます。 (しかし、ほとんどの場合、それをファイル名として扱い、他の投稿の状態と同じように_includeパス_で検索します。)

#include" file "`形式が使われている場合、サポートされていれば、実装はまず与えられた名前のファイルを探します。 そうでない(サポートされている)場合、または検索が失敗した場合、実装は他の( `#include)形式が使用されたかのように動作します。

また、3番目の形式が存在し、 `#include`ディレクティブが上記の形式のどちらとも一致しないときに使われます。 この形式では、(マクロ展開のような)いくつかの基本的な前処理は `#include`ディレクティブの"オペランド "に対して行われ、その結果は他の二つの形式のうちの一つと一致すると期待されます。


99


ここでのいくつかの良い答えはC標準を参照しているがPOSIX標準、特にhttp://pubs.opengroup.org/onlinepubs/9699919799/utilities/c99.html [c99の特定の振る舞いを忘れていました。 Cコンパイラ)]コマンド。

https://www2.opengroup.org/ogsys / catalog / C138 [The Open Group Base Specifications Issue 7]によると、

_ _ * -I * directory

絶対パス名ではないヘッダーを検索するためのアルゴリズムを変更して、通常の場所を調べる前に_directory_パス名で指定されたディレクトリを探すようにします。 したがって、名前が二重引用符( "")で囲まれているヘッダーは、最初に*#include 行を使用してファイルのディレクトリで検索され、次に -I オプションで指定されたディレクトリで検索されます。場所です。 名前が山かっこ( "<>")で囲まれているヘッダーの場合、ヘッダーは -I *オプションで指定されたディレクトリ内で、次に通常の場所でのみ検索されます。 * -I *オプションで指定されたディレクトリは、指定された順序で検索されます。 実装は、単一の_c99_コマンド呼び出しでこのオプションの少なくとも10個のインスタンスをサポートしなければならない。 _ _

したがって、POSIX準拠のCコンパイラを使用したPOSIX準拠の環境では、 #include" file.h "が最初に。/ file.h を検索することになります。ここで .はファイルのあるディレクトリです。 `#include`ステートメントでは、 #include は最初に / usr / include / file.h`を検索するでしょう。ここで `/ usr / include`はあなたのシステムで定義されたヘッダのための通常の場所です(それはPOSIXでは定義されていません。


40


両者の違いについては、https://gcc.gnu.org/onlinedocs/cpp/Include-Syntax.html [GCCの文書による]

_ _ — -- ユーザーヘッダファイルとシステムヘッダファイルの両方が前処理指令* ʻ#include` *を使ってインクルードされます。 それは2つの亜種があります。

_ _ * #include *

この変種はシステムヘッダファイルに使用されます。 システムディレクトリの標準リストでfileという名前のファイルを検索します。 このリストの前にディレクトリを `-I`オプションで追加することができます(https://gcc.gnu.org/onlinedocs/cpp/Invocation.html#Invocation[Invocation]を参照)。

  • #include" file " *

この変種はあなた自身のプログラムのヘッダファイルに使われます。 それは最初に現在のファイルを含んでいるディレクトリの中で、そして引用ディレクトリの中で、そして次に のために使われたのと同じディレクトリの中でfileという名前のファイルを検索します。 -iquote`オプションでクォートディレクトリのリストの前にディレクトリを追加することができます。 引用符または山括弧で区切られているかにかかわらず、 #include ''の引数はコメントが認識されず、マクロ名が展開されないという点で文字列定数のように振る舞います。 したがって、 `#include 'は x / * y `という名前のシステムヘッダファイルのインクルードを指定します。

ただし、ファイル内に円記号がある場合、それらは通常のテキスト文字と見なされ、エスケープ文字とは見なされません。 Cの文字列定数に適した文字エスケープシーケンスは処理されません。 したがって、 #include" x \ n \\ y "`は3つのバックスラッシュを含むファイル名を指定します。 (一部のシステムでは、「\」がパス名の区切り文字として解釈されます。 これらはすべて「/」も同じように解釈します。 ` / '`のみを使用するのが最も移植性があります。)

ファイル名の後の行に(コメント以外の)何かがあると、エラーになります。 _ _

 — -- _ _


39


します:

"mypath/myfile" is short for ./mypath/myfile

.`は#include`が含まれているファイルのディレクトリ、コンパイラの現在の作業ディレクトリ、あるいは `default_include_paths`のいずれかです。

and

 is short for /mypath/myfile

`。/`が ``の中にあれば、違いはありません。

`mypath / myfile`が他のインクルードディレクトリにある場合、動作は未定義です。


29


`` includeはプリプロセッサに `-I`ディレクトリと定義済みのディレクトリを最初に検索し、次に.cファイルのディレクトリを検索するように指示します。 `" file "`インクルードは、最初にソースファイルのディレクトリを検索し、それから `-I`に戻って定義済みになるようにプリプロセッサに指示します。 とにかくすべての目的地が検索され、検索の順序だけが異なります。

2011規格では、ほとんどの場合、「16.2ソースファイルのインクルード」でインクルードファイルについて説明しています。

_ _ 2形式の前処理指令

#改行を含む

<および>区切り文字の間の指定されたシーケンスによって一意的に識別されるヘッダーを見つけるために、実装で定義された場所のシーケンスを検索し、そのディレクティブをヘッダーの内容全体で置き換えます。 場所の指定方法または識別されたヘッダーの実装方法は実装によって異なります。

3形式の前処理指令

`#" q-char-sequence "改行を含む

区切り文字の間の指定されたシーケンスによって識別されるソースファイルの内容全体でそのディレクティブを置き換えます。 指定されたソースファイルは、実装定義の方法で検索されます。 この検索がサポートされていない場合、または検索が失敗した場合、ディレクティブは読み取りのように再処理されます。

#改行を含む

元のディレクティブからの同一の含まれたシーケンス(ある場合は>文字を含む)。 _ _

ファイルが見つからない場合、 ` xxx '`形式は `形式になります。 残りは実装定義です。


18


標準では - はい、違います。

_ _ * 次の形式の前処理指令

+

#include  new-line

`<`と `>`デリミタの間の指定されたシーケンスによって一意に識別されるヘッダのために実装定義の場所のシーケンスを検索し、ヘッダの内容全体でそのディレクティブを置き換えます。 場所の指定方法または識別されたヘッダーの実装方法は実装によって異なります。 * 次の形式の前処理指令

+

#include "q-char-sequence" new-line

`" `区切り文字の間の指定されたシーケンスによって識別されるソースファイルの内容全体でその指令を置き換えます。 指定されたソースファイルは、実装定義の方法で検索されます。 この検索がサポートされていない場合、または検索が失敗した場合、ディレクティブは読み取りのように再処理されます。

#include  new-line

元のディレクティブからの同一の含まれたシーケンス(もしあれば `>`文字を含む)。 * 次の形式の前処理指令

+

#include pp-tokens new-line

(これは、前の2つの形式のいずれとも一致しません)許可されています。 ディレクティブの `include`の後の前処理トークンは通常のテキストと同じように処理されます。 (現在マクロ名として定義されている各識別子は、その前処理トークンの置き換えリストに置き換えられます。)すべての置き換えの後に生成される指令は、前の2つの形式のうちの1つと一致します。 `<`と `>`の前処理トークンのペアまたは `" `の文字のペアの間の一連の前処理トークンを単一のヘッダ名前処理トークンに結合する方法は実装定義です。

定義:

  • h-char:改行を除くソース文字セットのメンバー 文字と >

  • q-char:改行を除くソース文字セットのメンバー 文字と `" ` _ _

規格は実装定義の方法の間のいかなる関係も伝えないことに注意してください。 最初の形式は一方の実装定義の方法で検索し、もう一方は(おそらく他の)実装定義の方法で検索します。 この規格では、特定のインクルードファイルが存在することも指定されています(たとえば、 ``)。

正式にはあなたのコンパイラのマニュアルを読まなければならないでしょうが、通常(伝統的に) #include" …​ "`フォームは最初に `#include`が見つかったファイルのディレクトリを検索し、次に#include <…​>`フォームが検索するディレクトリ(インクルードパス、例えばシステムヘッダ)。


14


素晴らしい答えをありがとう、特に。 Adam StelmaszczykとpiCookie、そしてaib。

多くのプログラマーのように、私はアプリケーション固有のファイルには myApp.hpp '`形式を使用し、ライブラリとコンパイラのシステムファイルには` 形式を使用します。 これが標準であると考えている間、ファイルは / I`と INCLUDE`環境変数で指定されています。

しかし、C規格では、検索順序は実装固有であると規定されているため、移植性が複雑になる可能性があります。 さらに悪いことに、我々はjamを使用します。これはインクルードファイルがどこにあるかを自動的に判断します。 インクルードファイルには相対パスまたは絶対パスを使用できます。 i.e.

#include "../../MyProgDir/SourceDir1/someFile.hpp"

MSVSの古いバージョンでは二重のバックスラッシュ(\\)が必要でしたが、現在はそれは必須ではありません。 いつ変わったのかわかりません。 'nixとの互換性のためにスラッシュを使用してください(Windowsはそれを受け入れます)。

本当に心配しているのであれば、ソースコードと同じディレクトリにあるインクルードファイルに `" ./myHeader.h "`を使ってください。管理上の問題)。

これはhttp://msdn.microsoft.com/en-us/library/36k2cdd4.aspx [MSDNの説明]です。

_ _ 引用フォーム

プリプロセッサは次の順序でインクルードファイルを検索します。

  1. #includeを含むファイルと同じディレクトリ内 ステートメント。

  2. 現在開いているインクルードファイルのディレクトリで、 +それらが開かれた逆順。 検索は、親のインクルードファイルのディレクトリから始まり、任意の祖父母のインクルードファイルのディレクトリを通って上方向に続きます。

  3. 各 `/ I`コンパイラオプションで指定されたパスに沿って。

  4. `INCLUDE`環境によって指定されたパスに沿って 変数。

山かっこ形式

プリプロセッサは次の順序でインクルードファイルを検索します。

  1. 各 `/ I`コンパイラオプションで指定されたパスに沿って。

  2. コンパイルがコマンドラインで、パスに沿って行われる場合 `INCLUDE`環境変数で指定されます。 _ _


13


少なくともGCCバージョン⇐ 3.0では、山括弧形式はインクルードファイルとインクルードファイルの間に依存関係を生成しません。

したがって、(GCCの-Mオプションを使用して)依存関係規則を生成したい場合は、依存関係ツリーに含める必要があるファイルに引用符付きの形式を使用する必要があります。

(http://gcc.gnu.org/onlinedocs/cpp/Invocation.htmlを参照)