includeディレクティブは、テキストファイルプロセッサに対し、ディレクティブのテキストを指定されたファイルの内容で置き換えるよう指示するものです。
インクルードという行為は、論理的な性質を持つ場合がある。プロセッサは、結合ファイルを作成することなく、ディレクティブが指定された場所にあるインクルードファイルの内容を単純に処理するだけかもしれない。
プロセッサによって構文が異なる場合があります。Cプリプロセッサ( C、C++およびその他のコンテキストで使用) では、インクルード ディレクティブは、#includeファイル指定で始まり、その後に続く行として定義されます。COBOLでは、コピーブックcopyをインクルードするために、で示されるインクルード ディレクティブが定義されます。
一般的に、C/C++ではincludeディレクティブはヘッダーファイルをインクルードするために使用されますが、任意のファイルをインクルードすることも可能です。比較的まれではありますが、 .cファイルなどの本体ファイルをインクルードするために使用されることもあります。
include ディレクティブは、カプセル化と再利用をサポートします。システムのさまざまな部分を論理的なグループに分割しつつ、ファイルインクルードによって互いに依存することができます。C および C++ は、include を活用するように設計されており、宣言と実装を分離することでビルド時間を最適化します。インクルードされる情報は、宣言のみに最小限に抑えることができます。
ファイルの内容を直接含めることには、過剰な定型コードや型/言語構文の認識不足など、重大な欠点があるため、新しい言語では include ディレクティブなしで設計されています。Go 、Python 、Haskellなどの言語は、 import ステートメントによるモジュール化をサポートしており、コンパイラ/インタプリタがモジュールをロードし、テキストを含めるのではなく、リンクされたモジュールを介してコードを解決します。Rustや Dなどのコンパイル言語は、コンパイル時にすべてのオブジェクト ファイルをリンクします。同様に、C++ もC++ モジュールをインポートする機能を導入しており、プリコンパイル ヘッダーと同様に、.pcmファイルを使用して中間ファイルを保存します。JavaとC#には がありますが、これらは include ディレクティブとは異なります。実際、これらの言語では、クラスはクラス ローダーによってオンデマンドでロードされ、名前空間でクラスを完全に修飾するだけでアクセスできます。これらの言語の import ステートメントは、クラスを現在のスコープに追加するためにのみ使用されます。importimportusing
C# は C プリプロセッサと同様のプリプロセッサ ディレクティブを使用する機能を持っていますが、#includeディレクティブは含まれていません。
C と C++ (C++20 以前) はどちらも、通常、#include指定されたファイルの内容でディレクティブ行を置き換える C プリプロセッサとともに使用されます。ファイルパスは、二重引用符 (例: "Header.h" ) または山括弧 (例: <Header.h> ) で囲まれます。[ 1 ]一部のプリプロセッサは、囲み文字に基づいてインクルードファイルの場所を異なる方法で探します。二重引用符で囲まれたパスはインクルードファイルからの相対パスとして扱われ、山括弧で囲まれたパスは、構成されたシステム検索パスのディレクトリのいずれかにあるものとして扱われます。[ 2 ]
include文の例:
// C 標準ヘッダー 'stdio.h' をインクルードします。おそらくその名前のファイルです。#include <stdio.h> // C++ 標準ヘッダー 'vector' をインクルードします。ファイルである場合もそうでない場合もあります。#include <vector> // 'MyHeader.h' という名前のカスタムヘッダーファイルをインクルードします。#include "MyHeader.h"include ディレクティブを使用すると、次のようなコードライブラリを開発できます。
Include ディレクティブはグロビング パターンをサポートしていないため、たとえば、現在のディレクトリ内のすべての*.hファイルを含めることはできません。#include"*.h"
2つのCソースファイルがあるとします。1つは関数を定義し、もう1つはその関数を使用します。インクルードディレクティブを使用せずに、関数を使用するファイルは関数プロトタイプadd()としてローカルに関数を宣言できます。
#pragma onceint add ( int , int );int triple ( int x ) { return add ( x , add ( x , x )); }このアプローチの欠点の1つは、関数プロトタイプが、その関数を呼び出す各ファイルに存在しなければならないことですadd()。もう1つの欠点は、シグネチャが変更された場合、それを使用する各ファイルを更新する必要があることです。プロトタイプを単一の別のファイルに配置することで、これらの問題を回避できます。プロトタイプをヘッダーファイルAdd.hに移動すると、使用するソースファイルは次のようになります。
#include "Add.h"int triple ( int x ) { return add ( x , add ( x , x )); }C言語およびC++言語において、ヘッダーファイルは、プログラマーがコードベースの宣言を共有および再利用できるようにするソースコードファイルであり、多くの場合、論理的に関連付けられたグループに分離して実装されます。
ヘッダーファイルは、関数、クラス、変数、プリプロセッサマクロなどのプログラミング要素を宣言します。ヘッダーファイルを使用すると、プログラマはヘッダーファイル内の共通の宣言に基づいて、複数の本体ファイルでプログラミング要素を使用できます。ヘッダーファイル内の宣言により、本体ファイルは実装コードを直接含めることなく実装を使用できます。ヘッダーはインターフェースと実装を分離します。[ 3 ]
複数のヘッダーファイルが同じファイルをインクルードすると、コンパイルエラーが発生する可能性があります。解決策の1つは、ヘッダーファイルでファイルをインクルードしないことです。ただし、本体ファイルに過剰なインクルードディレクティブが必要になる場合があります。もう1つの解決策は、各ヘッダーファイルにインクルードガードを使用することです。 [ 4 ]
C言語の標準ライブラリは、ヘッダーファイルの集合として宣言されます。C ++の標準ライブラリも同様ですが、宣言は実際のファイルを読み込むことなくコンパイラによって提供される場合があります。
C標準ヘッダーファイルは、.hファイル拡張子で命名されます。例: .h.cg#include<stdio.h>
山括弧で囲まれた C++ 標準ライブラリ名 (例: <vector> ) は宣言をインクルードしますが、ファイルからの宣言ではない可能性があります。[ 5 ]
C++20以降、C++はヘッダーユニット、つまりヘッダーから合成された個別の翻訳ユニットを介してインポートセマンティクスをサポートしています。 [ 6 ]これらはモジュールの完全な採用への過渡状態として使用されることを意図しています。
importC++26以降、 はプリプロセッサ ディレクティブではありません。したがって、C プリプロセッサでは処理されません。importは のようにコードをファイルにコピーするのではなく#include、コンパイル時に翻訳単位をリンクします。
例:
import < stdio . h > ; // このサポートはオプションですimport < vector > ; // このサポートは標準で義務付けられていますexport import "MyHeader.h" ;C++標準ライブラリのすべてのヘッダーにはヘッダーユニットが提供されています。[ 7 ]
C++20以降、モジュールが導入され、 を使用してインポートされますimport。これらはヘッダーユニットとしてインポートするのと同じ意味を持ちますが、エクスポートをより細かく制御できます。C ++26以降、これらはプリプロセッサによってまったく処理されません。インポートによってアクセスできるようにするには、 をマークしmodule、各シンボルをマークするexportか、ブロック内に配置する必要がありますexport。 ステートメントの意味は次のimportとおりです。
export optional import module_name;
C++23以降では、C++標準ライブラリは、と記述することでモジュールとしてインポートできます。importstd;
// C++標準ライブラリをインポートしますimport std ;// "acme.project.math.BigInteger" という名前のモジュールをインポートしますimport acme . project . math . BigInteger ;// "wikipedia.util.logging.Logger "という名前のモジュールをインポートし、それを再エクスポートします//このモジュールをインポートするファイルはすべて、推移的に wikipedia.util.logging.Logger をインポートしますexport import wikipedia.util.logging.Logger ;C23およびC++26で追加されたこの#embedディレクティブは、ディレクティブに似ています#includeが、バイナリリソースをソースコードに含めたり埋め込んだりするのに適しています。
constexpr char ICON_DISPLAY_DATA [] = { #embed "art.png" };// 整数定数式から初期化できる任意の型を指定しますconstexpr char RESET_BLOB [] = { #embed "data.bin" };// 属性も同様に機能しますalignas ( 8 ) constexpr char ALIGNED_DATA_STRING [] = { #embed "attributes.xml" };int main () { return #embed </dev/urandom> limit(1) ; }Objective-Cは C と同様にヘッダー ファイルを使用し、#includeディレクティブを持っています。ただし、#importディレクティブも持っていて、これは と同じように動作しますが#include、唯一の違いは、 は#includeガードや#pragma once#importを使用しなくても、ファイルのインクルードが 1 回以上発生しないことを保証することです。
#import <Foundation/Foundation.h> #import "MyClass.h"Objective-Cディレクティブは、C++ のステートメント (モジュールをインポートする) や、Microsoft Visual C++ディレクティブ (タイプライブラリをインポートする)#importと混同してはならない。 [ 8 ]import#import
COBOL (およびRPG IV ) では、プログラマーがコピーブックをプログラムのソースにコピーできます。これはインクルードに似ていますが、テキストの置換が可能です。インクルードの COBOL キーワードは でCOPY、置換は句を使用して行います。インクルード ディレクティブは COBOL 60 以降 COBOL に存在していましたが、元の[ 9 ]REPLACING ... BY ...から1968 年までに に変更されました。 [ 10 ]INCLUDECOPY
Fortran は、ヘッダー ファイル自体を必須とはしていません。しかし、Fortran 90 以降には、includeステートメントとモジュールという 2 つの関連機能があります。ステートメントは、C のヘッダーのように、プロシージャ インターフェースを含む共通ファイルを共有するために使用できますが、インターフェースの指定は、すべての種類の Fortran プロシージャで必須ではありません。この方法は一般的には使用されていません。代わりに、プロシージャは通常モジュールにグループ化され、useコードの他の領域でステートメントを使用して参照できます。モジュールの場合、ヘッダータイプのインターフェース情報はコンパイラによって自動的に生成され、通常は個別のモジュール ファイルに格納されますが、一部のコンパイラではこの情報をオブジェクト ファイルに直接格納しています。モジュール プロシージャ インターフェースはほぼ普遍的にこの方法で伝播されますが、言語仕様自体は追加ファイルの作成を義務付けていません。
Haskell言語は、Cプリプロセッサを記述することで使用でき{-# LANGUAGE CPP #-}、ディレクティブにアクセスできます#include。
ほとんどのPascalコンパイラは、$iまたは$includeコンパイラ ディレクティブをサポートしており、$iまたは$includeディレクティブは、次の形式のコメント ブロックの開始直後に記述されます。
{$i ''filename.pas''}(*$i ''filename.inc''*){$include ''filename.inc''}(*include ''filename.pas''*)/または/ディレクティブは大文字と小文字を区別$iせず、filename.pasまたはfilename.incはインクルードするファイルの名前です。(Pascal のインクルード ファイルに拡張子.incを付けるのが一般的ですが、必須ではありません。)コンパイラによっては、無制限の再帰を防ぐために、インクルード ファイルの呼び出しを特定の数に制限したり、自身や現在開いているファイルの呼び出しを禁止したり、一度に最大 1 つのインクルード ファイルに制限したりします。たとえば、インクルード ファイルは自身や他のファイルをインクルードすることはできません。ただし、他のファイルをインクルードするプログラムは、一度に 1 つずつ、複数のファイルをインクルードできます。$I$include$INCLUDE
PHPでは、includeディレクティブにより別の PHP ファイルがインクルードされ、評価されます。[ 11 ]同様のコマンドには、インクルードに失敗すると致命的な例外requireが発生し、スクリプトが停止するコマンド、[ 12 ]および、既にインクルードまたは要求されているファイルが再度インクルードまたは要求されるのを防ぎ、C 言語の二重インクルードの問題を回避するコマンドがあります。include_oncerequire_once
Rustにはマクロがありinclude!、これは基本的にC言語のものと同じように動作します。#includeコンテキストに応じて、項目を式または項目として解析します。[ 13 ]
include! ( "generated_code.rs" );fn main () { // ... generated_code.rs の項目を使用する}しかし、C言語とは異なり、これはコードの分離とインクルードの一般的な方法ではありません。代わりに、Rustはモジュールを使用し、名前空間とカプセル化を維持します。
Rust は、include_str!ファイル全体をインクルードして文字列に格納できるマクロもサポートしています。[ 14 ]同様にマクロもありますinclude_bytes!。
let my_str : & ' static str = include_str! ( "spanish.in" ); let bytes : & ' static [ u8 ] = include_bytes! ( "spanish.in" );includeディレクティブを持つその他の注目すべき言語:
include...( Fortran、MASM )<!--#include ...-->(HTML SSI )var...=require("...");( CommonJSを使用したJavaScript )<%@include...%>( JSP )%include ...( PL/I )/COPY QCPYLESRC,QBC(RPG IVの場合、最初の引数はファイル名、2番目の引数はコピーブックです)local...=require("...")( Lua )現代のプログラミング言語(HaskellやJavaなど)は、includeディレクティブ構造を避け、モジュールとimport/exportセマンティクスを優先する傾向があります。これらの言語の中には(JavaやC#など)、前方宣言を使用せず、代わりにソースファイルから識別子を自動的に認識し、動的ライブラリシンボル(通常はimportまたはusingディレクティブで参照される)から直接読み取るものもあります。
<ん>。