include
CおよびC++プログラミング言語では、次のように、山かっこを使用することとステートメントで引用符を使用することの違いは何ですか?
#include <filename>
#include "filename"
include
CおよびC++プログラミング言語では、次のように、山かっこを使用することとステートメントで引用符を使用することの違いは何ですか?
#include <filename>
#include "filename"
実際には、違いはプリプロセッサがインクルードされたファイルを検索する場所にあります。
#include <filename>
実装に依存する方法でのプリプロセッサ検索の場合、通常はコンパイラ/IDEによって事前に指定された検索ディレクトリで検索します。このメソッドは通常、標準ライブラリヘッダーファイルをインクルードするために使用されます。
プリプロセッサの場合#include "filename"
、最初にディレクティブを含むファイルと同じディレクトリを検索し、次に#include <filename>
フォームに使用される検索パスに従います。このメソッドは通常、プログラマー定義のヘッダーファイルをインクルードするために使用されます。
より完全な説明は、検索パスに関するGCCのドキュメントに記載されています。
知る唯一の方法は、実装のドキュメントを読むことです。
C規格のセクション6.10.2のパラグラフ2から4には、次のように記載されています。
フォームの前処理ディレクティブ
#include <h-char-sequence> new-line
と区切り文字の間の指定されたシーケンスによって一意に識別されるヘッダーの実装定義の場所のシーケンスを検索し、そのディレクティブをヘッダーのコンテンツ全体に置き換えます。場所の指定方法または識別されるヘッダーの方法は、実装によって定義されます。
<
>
フォームの前処理ディレクティブ
#include "q-char-sequence" new-line
そのディレクティブを、区切り文字間の指定されたシーケンスによって識別されるソースファイルのコンテンツ全体に置き換えます。
"
名前付きソースファイルは、実装定義の方法で検索されます。この検索がサポートされていない場合、または検索が失敗した場合、ディレクティブは次のように再処理されます。#include <h-char-sequence> new-line
元のディレクティブからの同一の含まれるシーケンス(
>
存在する場合は文字を含む)を使用します。フォームの前処理ディレクティブ
#include pp-tokens new-line
(前の2つの形式のいずれにも一致しません)が許可されます。ディレクティブの後の前処理トークン
include
は、通常のテキストと同じように処理されます。(現在マクロ名として定義されている各識別子は、前処理トークンの置換リストに置き換えられます。)すべての置換の後に生じるディレクティブは、前の2つの形式のいずれかに一致する必要があります。<
と>
前処理トークンのペアまたは文字のペアの間の一連の前処理トークンを"
組み合わせて単一のヘッダー名前処理トークンにする方法は、実装によって定義されます。定義:
h-char:改行文字と
>
q-char:改行文字と
"
<と>の間の文字のシーケンスは、ヘッダーを一意に参照しますが、これは必ずしもファイルではありません。実装は、文字シーケンスを自由に使用できます。(ただし、ほとんどの場合、他の投稿の状態と同様に、ファイル名として扱い、インクルードパスで検索を実行します。)
フォームが使用されている場合#include "file"
、実装は、サポートされている場合、最初に指定された名前のファイルを探します。そうでない場合(サポートされている場合)、または検索が失敗した場合、実装は他の(#include <file>
)形式が使用されたかのように動作します。
また、3番目の形式が存在し、#include
ディレクティブが上記のいずれの形式とも一致しない場合に使用されます。この形式では、いくつかの基本的な前処理(マクロ展開など)が#include
ディレクティブの「オペランド」で実行され、結果は他の2つの形式のいずれかに一致することが期待されます。
ここでのいくつかの良い答えは、C 標準を参照していますが、POSIX 標準、特にc99 (C コンパイラなど)コマンドの特定の動作を忘れていました。
The Open Group Base Specifications Issue 7によると、
-I ディレクトリ
名前が絶対パス名ではないヘッダーを検索するアルゴリズムを変更して、通常の場所を検索する前に、ディレクトリパス名で指定されたディレクトリを検索します。したがって、名前が二重引用符 ( "" ) で囲まれているヘッダーは、最初に#include行のあるファイルのディレクトリで検索され、次に-Iオプションで指定されたディレクトリで検索され、最後に通常の場所で検索されます。名前が山括弧 ( "<>" ) で囲まれているヘッダーの場合、ヘッダーは-Iオプションで指定されたディレクトリでのみ検索され、次に通常の場所で検索されます。-Iオプションで指定されたディレクトリは、指定された順序で検索されます。c99コマンドの呼び出し。
したがって、POSIX 準拠の環境では、POSIX 準拠の C コンパイラを使用して、最初#include "file.h"
に検索する可能性があります。 where is the directory where is the file with the statement, whileは、最初に検索する可能性が高く、 where is your system definedヘッダーの通常の場所(POSIX で定義されていないようです)。./file.h
.
#include
#include <file.h>
/usr/include/file.h
/usr/include
プリプロセッサの正確な動作は、コンパイラによって異なります。次の回答は、GCC およびその他のいくつかのコンパイラに適用されます。
#include <file.h>
file.h
たとえば、MinGW の場合、コンパイラはC:\MinGW\include\ またはコンパイラがインストールされている場所を検索します。
#include "file"
は、現在のディレクトリ (つまり、ソース ファイルが存在するディレクトリ) で を検索するようにコンパイラに指示しますfile
。
GCCのフラグを使用し-I
て、山かっこで囲まれたインクルードに遭遇したときに、ディレクトリ内のヘッダーも検索する必要があることを伝えることができます-I
。GCC は、フラグの後のディレクトリをディレクトリであるかのように扱いincludes
ます。
たとえば、myheader.h
自分のディレクトリで呼び出されたファイルがある#include <myheader.h>
場合、GCC をフラグ-I .
(現在のディレクトリでインクルードを検索する必要があることを示す) で呼び出したかどうかを言うことができます。
-I
フラグがない場合は#include "myheader.h"
、ファイルをインクルードするために使用するか、コンパイラmyheader.h
のディレクトリに移動する必要があります。include
します:
"mypath/myfile" is short for ./mypath/myfile
が含まれ.
ているファイルのディレクトリ#include
、および/またはコンパイラの現在の作業ディレクトリ、および/またはdefault_include_paths
と
<mypath/myfile> is short for <defaultincludepaths>/mypath/myfile
./
にある場合<default_include_paths>
、違いはありません。
mypath/myfile
が別のインクルード ディレクトリにある場合、動作は未定義です。
インクルードは、最初にディレクトリと事前定義されたディレクトリを検索し、次に.c ファイルのディレクトリ<file>
を検索するようにプリプロセッサに指示します。インクルードは、プリプロセッサに、最初にソース ファイルのディレクトリを検索し、次に定義済みに戻すように指示します。いずれにせよ、すべての目的地が検索されます。検索の順序が異なるだけです。-I
"file"
-I
2011 規格では、主に「16.2 ソース ファイル インクルード」でインクルード ファイルについて説明しています。
2 次の形式の前処理ディレクティブ
# include <h-char-sequence> new-line
< と > 区切り文字の間の指定されたシーケンスによって一意に識別されるヘッダーの実装定義の場所のシーケンスを検索し、そのディレクティブをヘッダーの内容全体で置き換えます。場所がどのように指定されるか、またはヘッダーが識別される方法は、実装によって定義されます。
3 フォームの前処理ディレクティブ
# include "q-char-sequence" new-line
このディレクティブは、" デリミタ間の指定されたシーケンスで識別されるソース ファイルの内容全体に置き換えられます。指定されたソース ファイルは、実装定義の方法で検索されます。この検索がサポートされていない場合、または検索が失敗した場合は、 、ディレクティブは読み取ったかのように再処理されます
# include <h-char-sequence> new-line
元のディレクティブからの同一の含まれるシーケンス (存在する場合は > 文字を含む) を使用します。
ファイルが見つからない場合、フォームは"xxx"
フォームに劣化することに注意してください。<xxx>
残りは実装定義です。
少なくともGCCバージョン<=3.0の場合、山かっこ形式は、含まれているファイルと含まれているファイルの間に依存関係を生成しません。
したがって、依存関係ルールを生成する場合(たとえば、GCC -Mオプションを使用)、依存関係ツリーに含める必要のあるファイルには引用符で囲まれた形式を使用する必要があります。
(http://gcc.gnu.org/onlinedocs/cpp/Invocation.htmlを参照してください)
素晴らしい答えをありがとう、特に。Adam Stelmaszczyk と piCookie、そして aib.
多くのプログラマーと同様に、私は、"myApp.hpp"
アプリケーション固有のファイルにはフォームを使用し<libHeader.hpp>
、ライブラリおよびコンパイラ システム ファイル (つまり/I
、INCLUDE
環境変数で指定されたファイル) にはフォームを使用するという非公式の規則を使用してきましたが、それが標準であると何年も考えてきました。
ただし、C 標準では、検索順序は実装固有であると規定されているため、移植性が複雑になる可能性があります。さらに悪いことに、インクルード ファイルがどこにあるかを自動的に把握する jam を使用します。インクルード ファイルには相対パスまたは絶対パスを使用できます。すなわち
#include "../../MyProgDir/SourceDir1/someFile.hpp"
古いバージョンの MSVS では二重のバックスラッシュ (\\) が必要でしたが、現在は必要ありません。いつ変わったのかわからない。'nix との互換性のためにスラッシュを使用してください (Windows はそれを受け入れます)。
本当に心配なら"./myHeader.h"
、ソース コードと同じディレクトリにあるインクルード ファイルを使用してください (私の現在の非常に大きなプロジェクトには、いくつかの重複したインクルード ファイル名が散らばっています。これは構成管理の問題です)。
便宜上、ここにコピーされたMSDNの説明を次に示します)。
引用形式
プリプロセッサは、次の順序でインクルード ファイルを検索します。
- #include ステートメントを含むファイルと同じディレクトリ。
- 現在開いているインクルード ファイルのディレクトリで、開いたときと逆の順序で
。検索は、親のインクルード ファイルのディレクトリから始まり、親の親のインクルード ファイル
のディレクトリまで上方向に進みます。/I
各コンパイラ オプションで指定されたパスに沿って。INCLUDE
環境変数で指定されたパスに沿って。山かっこ形式
プリプロセッサは、次の順序でインクルード ファイルを検索します。
/I
各コンパイラ オプションで指定されたパスに沿って。INCLUDE
環境変数によって指定されたパスに沿って、コマンド ラインでコンパイルが行われる場合。
コンパイラの場合#include ""
、通常、そのインクルードを含むファイルのフォルダーを検索してから、他のフォルダーを検索します。コンパイラは#include <>
、現在のファイルのフォルダーを検索しません。
山括弧付きの #include は、インクルードするファイルの「実装に依存する場所のリスト」(「システム ヘッダー」と言う非常に複雑な方法) を検索します。
引用符付きの #include は、ファイルを検索するだけです(そして、「実装に依存する方法で」、ブレ)。つまり、通常の英語では、投げたパス/ファイル名を適用しようとし、システムパスを追加したり、改ざんしたりしません。
また、#include "" が失敗した場合は、標準で #include <> として読み直されます。
gccのドキュメントには、標準ではなく gcc に固有の (コンパイラ固有の) 説明がありますが、ISO 標準の弁護士スタイルの話よりもはるかに理解しやすいものです。
#include <>
事前定義されたヘッダーファイル用ですヘッダーファイルが事前定義されている場合は、ヘッダーファイル名を角かっこで囲むだけで、次のようになります(事前定義されたヘッダーファイル名iostreamがあると仮定します)。
#include <iostream>
#include " "
プログラマーが定義するヘッダーファイル用ですあなた(プログラマー)があなた自身のヘッダーファイルを書いたなら、あなたは引用符でヘッダーファイル名を書くでしょう。したがって、と呼ばれるヘッダーファイルを作成したとするとmyfile.h
、これは、includeディレクティブを使用してそのファイルをインクルードする方法の例です。
#include "myfile.h"
ここでの回答の多くは、ファイルを見つけるためにコンパイラが検索するパスに焦点を当てています。これはほとんどのコンパイラが行うことですが、準拠するコンパイラは、標準ヘッダーの効果を事前にプログラムして、たとえば#include <list>
スイッチとして扱うことが許可されており、ファイルとして存在する必要はまったくありません。
これは単なる仮説ではありません。そのように動作するコンパイラが少なくとも 1 つあります。#include <xxx>
標準ヘッダーのみを使用することをお勧めします。
#include "filename" // User defined header
#include <filename> // Standard library header.
例:
ここでのファイル名は次のSeller.h
とおりです。
#ifndef SELLER_H // Header guard
#define SELLER_H // Header guard
#include <string>
#include <iostream>
#include <iomanip>
class Seller
{
private:
char name[31];
double sales_total;
public:
Seller();
Seller(char[], double);
char*getName();
#endif
クラスの実装 (たとえば、Seller.cpp
や、ファイルを使用する他のファイルSeller.h
) では、ユーザーが定義したヘッダーを次のように含める必要があります。
#include "Seller.h"
#include <filename>
システムファイルを参照する場合に使用します。/usr/include
これは、や などのシステムのデフォルトの場所にあるヘッダー ファイルです/usr/local/include
。別のプログラムに含める必要がある独自のファイルについては、#include "filename"
構文を使用する必要があります。
単純な一般的なルールは、山括弧を使用して、コンパイラに付属するヘッダー ファイルを含めることです。二重引用符を使用して、他のヘッダー ファイルを含めます。ほとんどのコンパイラはこのようにします。
1.9 — ヘッダー ファイルでは、プリプロセッサ ディレクティブについて詳しく説明しています。あなたが初心者のプログラマーである場合、そのページはすべてを理解するのに役立つはずです. 私はここでそれを学び、仕事でそれに従っています。
#include <filename>
C/C++システムやコンパイラライブラリのヘッダファイルを利用したい場合に使用します。これらのライブラリは、stdio.h、string.h、math.h などです。
#include "path-to-file/filename"
プロジェクトフォルダーまたは他の場所にある独自のカスタムヘッダーファイルを使用する場合に使用されます。
プリプロセッサとヘッダーの詳細については。C-プリプロセッサを読んでください。
現在の構成に基づいて、gcc を使用してシステムの検索順序を確認するには、次のコマンドを実行します。このコマンドの詳細については、こちらを参照してください
cpp -v /dev/null -o /dev/null
Apple LLVM バージョン 10.0.0 (clang-1000.10.44.2)
ターゲット: x86_64-apple-darwin18.0.0
スレッド モデル: posix インストール ディレクトリ: Library/Developer/CommandLineTools/usr/bin
"/Library/Developer/CommandLineTools/usr/bin/clang" -cc1 -triple x86_64-apple-macosx10.14.0 -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -E -disable-free - disable-llvm-verifier -discard-value-names -main-file-name null -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -fno-strict-return -masm-verbose - munwind-tables -target-cpu penryn -dwarf-column-info -debugger-tuning=lldb -target-linker-version 409.12 -v -resource-dir /Library/Developer/CommandLineTools/usr/lib/clang/10.0.0 - isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk -I/usr/local/include -fdebug-compilation-dir /Users/hogstrom -ferror-limit 19 -fmessage-length 80 -stack-protector 1 -fblocks -fencode-extended-block-signature -fobjc-runtime=macosx-10.14.0 -fmax-type-align=16 -fdiagnostics-show-option -fcolor-diagnostics -traditional-cpp -o - -xc /dev/null
clang -cc1 バージョン 10.0.0 (clang-1000.10.44.2) デフォルト ターゲット x86_64-apple-darwin18.0.0 存在しないディレクトリを無視 「/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/local/include」 directory "/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/Library/Frameworks"
#include "..." 検索はここから開始:
#include <...> 検索はここから開始:
/usr/local/include
/ Library/Developer/CommandLineTools/usr/lib/clang/10.0.0/include
/Library/Developer/CommandLineTools/usr/include
/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include
/Library/Developer/ CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks (フレームワーク ディレクトリ)
検索リストの終わり。