c++ - handling - c variable arguments




#include<ファイル名>と#include“ファイル名”の違いは何ですか? (19)

"<filename>"は標準Cライブラリの場所を検索します。

一方、 "filename"は現在のディレクトリも検索します。

理想的には、標準のCライブラリには<...>を使用し、作成して現在のディレクトリに存在するライブラリには "..."を使用します。

CおよびC ++プログラミング言語では、次のように、 include 文で山括弧を使用することと引用符を使用することの違いは何ですか。

  1. #include <filename>
  2. #include "filename"

#include <filename>

C / C ++システムまたはコンパイラライブラリのヘッダファイルを使用したい場合に使用します。 これらのライブラリはstdio.h、string.h、math.hなどです。

#include "path-to-file/filename"

プロジェクトフォルダまたは他の場所にある独自のカスタムヘッダファイルを使用する場合に使用されます。

プリプロセッサとヘッダの詳細については。 C - プリプロセッサ を読んでください 。


#include文を書くには2つの方法があります。

#include"filename"
#include<filename>

各形式の意味は

#include"mylib.h"

このコマンドは、 mylib.h 設定されている可能性のあるインクルード検索パスで指定されているように、現在のディレクトリ内 のファイル と指定されたディレクトリのリストを検索します。

#include<mylib.h>

このコマンドはファイルを探します mylib.h 、指定されたディレクトリのリストだけで 。

インクルード検索パスは、インクルードされているファイルを検索するディレクトリのリストに他なりません。異なるCコンパイラでは、検索パスをさまざまな方法で設定できます。


<>と ""が大きな違いを生む状況に遭遇しました(VS 2017)。

「ABC」と「XYZ」という2つのプロジェクトがあります。 それぞれ " "(vg。 と ) という名前の 異なる プリコンパイル済みヘッダーを 使用します 。 precomp.h \ABC\precomp.h \XYZ\precomp.h

一部のCPPファイルは両方のプロジェクトで使用されています。 たとえば、file \ABC\MOD1.CPP はプリコンパイル済みヘッダーを使用し ます 。 MOD1.CPPが XYZ に 含まれるとき 、これを書くと

#include "precomp.h"

... \ABC\precomp.h (.CPPファイルと同じディレクトリから作成された)インクルードされますが、これはまったく間違っています。

私が書いた場合:

#include <precomp.h>

これが使用されますが \XYZ\precomp.h 、これは正しいバージョンのヘッダーです。


現在の設定に基づいて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
"/ライブラリ/ Developer / CommandLineTools / usr / bin / clang" -cc1 - トリプルx86_64-アップル-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 -mスレッドモデル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 /ライブラリ/ Developer / CommandLineTools / usr / lib / clang / 10 - 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 -f診断診断表示オプション-fcolor診断-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"は存在しないを無視しますディレクトリー "/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/Library/Frameworks"
#include "..."ここから検索が開始されます:
#include <...>ここで検索が開始されます:
/ usr / local / include
/ライブラリ/ 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 /システム/ライブラリ/ Frameworks (フレームワークディレクトリ)
検索リストの終わり。


#include <ファイル名>を使用すると、プリプロセッサはC \ C ++ヘッダーファイルのディレクトリ(stdio.h \ cstdio、文字列、ベクトルなど)でファイルを探します。 しかし、あなたが#include "filename"を使用するとき:最初に、プリプロセッサは現在のディレクトリでファイルを探します、そしてそれがここにないなら - 彼はC \ C ++ヘッダファイルのディレクトリでそれを探します。


C ++では、2つの方法でファイルをインクルードします。

最初のものは#includeで、事前に定義されたデフォルトの場所にあるファイルを探すようにプリプロセッサに指示します。 この場所は、多くの場合、ファイルを含めるパスを示すINCLUDE環境変数です。

そして2番目のタイプは#include "filename"で、これは最初に現在のディレクトリでファイルを探すようにプリプロセッサに指示し、次にユーザーが設定した事前定義された場所でそれを探すように指示します。


ここでのいくつかの良い答えはC標準を参照していますが、POSIX標準、特に c99(Cコンパイラなど) コマンドの特定の動作を忘れていました。

The Open Groupの基本仕様第7号に よると、

-I ディレクトリ

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

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


します:

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

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

そして

<mypath/myfile> is short for <defaultincludepaths>/mypath/myfile

./<default_include_paths> 場合、それは違いを生じません。

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


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

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

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

より完全な説明は 、検索パスに関する GCCの ドキュメントにあります


山括弧付きの#includeは、インクルードされるファイルについて「実装依存の場所のリスト」(これは「システムヘッダー」と言うのは非常に複雑な方法です)を検索します。

引用符を含む#includeはファイルを検索するだけです(そして「実装依存の方法で」、bleh)。 これは、通常の英語では、あなたがそれに投げかけたパス/ファイル名を適用しようと試みるでしょうし、そうでなければシステムパスを追加したり改ざんしたりしないことを意味します。

また#include ""が失敗した場合、標準では#include <>として再読み込みされます。

g++ には(コンパイラ固有の)説明がありますが、これは標準ではなくgccに固有のものですが、ISO標準の弁護士形式の話よりもはるかに理解しやすいものです。


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

  • 次の形式の前処理指令

    #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 た後の前処理トークン include 、通常のテキストと同じように処理されます。 (現在マクロ名として定義されている各識別子は、前処理トークンの置換リストに置き換えられます。)すべての置換の後に生成される指令は、前の2つの形式のいずれかに一致します。 <> 前処理トークンのペアまたは一対の " 文字 " 間の一連の前処理トークンを単一のヘッダー名前処理トークンに結合する方法は、実装定義です。

定義:

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

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

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

正式にはコンパイラのマニュアルを読む必要がありますが、通常は(通常は) #include "..." 形式で #include が最初に見つかったファイルのディレクトリを検索し、次に #include <...> #include が見つかったディレクトリを検索します。 #include <...> フォーム検索(インクルードパス、システムヘッダーなど)。


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

多くのプログラマーと同様に、私はアプリケーション固有のファイルには "myApp.hpp" 形式を使用し、ライブラリとコンパイラのシステムファイルには <libHeader.hpp> 形式、つまり /IINCLUDE 環境変数で指定されたファイルを使用します。何年もの間、それが標準だと思っていました。

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

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

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

本当に 気になる場合は、ソースコードと同じディレクトリにあるインクルードファイルに "./myHeader.h" を使用して "./myHeader.h" (私の現在の非常に大きなプロジェクトでは、インクルードファイルの名前が重複しています - 実際には構成管理の問題です) )

これは MSDNの説明を コピーしたものです。

引用形式

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

  1. #includeステートメントを含むファイルと同じディレクトリにあります。
  2. 現在開いているインクルードファイルのディレクトリでは、逆の順序で
    彼らは開かれました。 検索は、親インクルードファイルのディレクトリから開始されます。
    任意の祖父母のインクルードファイルのディレクトリを通して上向きに続きます。
  3. /I コンパイラー・オプションで指定されたパスに沿って。
  4. INCLUDE 環境変数で指定されたパスに沿って。

山かっこ形式

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

  1. /I コンパイラー・オプションで指定されたパスに沿って。
  2. INCLUDE 環境変数で指定されたパスに沿って、コマンド行でコンパイルが行われたとき。

GCCのドキュメントには 、両者の違いについて次のように 記載されて います。

ユーザーヘッダファイルとシステムヘッダファイルの両方が、前処理指令 '#include' を使用してインクルードされます。 2つの亜種があります。

#include <file>

この変種はシステムヘッダファイルに使用されます。 システムディレクトリの標準リストでfileという名前のファイルを検索します。 このリストの -I オプションを付けてディレクトリを追加することができます( Invocation 参照)。

#include "file"

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

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

ファイル名の後の行に(コメント以外の)何かがある場合、それはエラーです。


#include <file.h> は、 "includes"ディレクトリでヘッダを検索するようにコンパイラに指示します。たとえば、MinGWの場合、コンパイラはC:\ MinGW \ include \またはコンパイラがインストールされている場所で file.h を検索します。

#include "file" は、現在のディレクトリ(つまり、ソースファイルが存在するディレクトリ)で file を検索するようにコンパイラに指示し file

GCCに -I フラグを使用すると、角括弧付きのインクルードに遭遇したときに、 -I 後にディレクトリ内のヘッダーも検索するように指示できます。 GCCはフラグの後のディレクトリを、それが includes ディレクトリであるかのように扱います。

たとえば、自分のディレクトリに myheader.h というファイルがある場合、GCCに -I . フラグを付けて呼び出すと、 #include <myheader.h> と言うことができます -I . (現在のディレクトリでインクルードを検索する必要があることを示します。)

-I フラグを指定しないと、ファイルをインクルードするために #include "myheader.h" を使用するか、 myheader.h をコンパイルの include ディレクトリに移動する必要があります。


#include <filename> システムファイルが参照されているときに使用されます。 それは次のようなシステムのデフォルトの場所にあるヘッダーファイルです。 /usr/include か、 /usr/local/include 。 他のプログラムに含まれる必要があるあなた自身のファイルのためにあなたは #include "filename" 構文 を使用しなければなりません 。


#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 <abc.h>

標準ライブラリファイルをインクルードするために使用されます。 そのため、コンパイラは標準ライブラリヘッダが存在する場所をチェックします。

#include "xyz.h"

ユーザー定義のヘッダーファイルをインクルードするようコンパイラーに指示します。 そのため、コンパイラは現在のフォルダまたは -I 定義されたフォルダでこれらのヘッダファイルをチェックします。


  • #include <> は事前定義済みヘッダーファイル用です。

ヘッダファイルが事前定義されている場合は、単にヘッダファイル名を角括弧で囲むと、次のようになります(事前定義されたヘッダファイル名iostreamがあると仮定します)。

#include <iostream>
  • #include " " はプログラマが定義するヘッダファイル用です。

あなた(プログラマー)があなた自身のヘッダファイルを書いたなら、あなたは引用符でヘッダファイル名を書くでしょう。 そのため、 myfile.h というヘッダーファイルを作成したとします。これは、includeディレクティブを使用してそのファイルをインクルードする方法の例です。

#include "myfile.h"




c-preprocessor