ホームページ  >  記事  >  php教程  >  extern の使用法の概要

extern の使用法の概要

高洛峰
高洛峰オリジナル
2016-12-19 14:36:251334ブラウズ

Extern の問題は、このキーワードが出現したときに、それが宣言なのか定義なのかがわからないことです。

覚えておいてください: 宣言は複数回行うことができますが、定義は 1 回だけ行うことができます。

関数宣言の extern キーワードはオプションです。関数自体が変更されなければ extern であるためです。ただし、引用する際にはやはり宣言する必要があります。

グローバル変数を外部で宣言する場合、externキーワードが必要です。変数がextern変更されておらず、明示的に初期化されていない場合、それも変数の定義となるため、この時点でexternを追加する必要があり、コンパイラはそれを保存します。このタグ内 スペースは実行時にメモリにロードされ、0 に初期化されます。ローカル変数の宣言は extern で変更できず、ローカル変数は実行時にスタック部分にメモリを割り当てるだけです。 Linuxのgccリンク解析では


参照宣言、定義宣言

強いシンボル、弱いシンボル

が登場し、リンクの理解を深めることができます。

グローバル変数と関数の間には本質的に違いはありません。関数名は関数バイナリ ブロックの先頭へのポインターです。グローバル変数は、関数の外部で宣言された変数です。関数名も関数の外にあるため、関数もグローバルです。

使用するときは、スタイルを形成してください。

ヘッダー ファイル

まず、ヘッダー ファイルについて説明します。実際、ヘッダー ファイルはプリコンパイル中に #include の場所に展開されるだけで、他の意味はありません。実際、ヘッダー ファイルは主に他の人が見るためのものです。

試しにヘッダーファイルのサフィックスをxxx.txtに変更し、

#include "xxx.txt"

を使用してヘッダーファイルが参照されている箇所をコンパイルしたところ、リンクがスムーズに進みました。ヘッダー ファイルはコードを読み取るためだけであり、他の機能はないことがわかります。

C であろうと C++ であろうと、関数、変数、構造体、クラスなどを .c または .cpp ファイルに置きます。次に、それを lib、dll、obj、.o などにコンパイルし、他の人が使用するときに最も基本的な gcc hisfile.cpp yourfile.o|obj|dll|lib などを使用します。
しかし、私たちプログラマーにとって、ライブラリや DLL の内容をどうやって知るのでしょうか...?それはヘッダーファイルによって異なります。ヘッダー ファイルはユーザーへの説明です。機能、パラメータ、各種インターフェースの説明。
説明なのでヘッダーファイルに置くのは当然関数や変数、クラスについての「宣言」です。これは「定義」ではなく「声明」であることに注意してください。
それで、皆さんは宣言と定義の違いを知っていると思います。したがって、ヘッダー ファイルには愚かな定義をしないことが最善です。たとえば、グローバル変数:

#ifndef _XX_header file.H
#define _XX_header file.H
int A;
#endif

そして、非常に悪いのは、ここでの int A がグローバル変数の定義であることです。したがって、このヘッダー ファイルが複数回参照されると、A が繰り返し定義されることになります
明らかに構文が間違っています。しかし、この #ifndef 条件付きコンパイルを使用すると、ヘッダー ファイルが 1 回だけ参照されるようにできますが、それでもエラーが発生する可能性があります。ただし、複数の c ファイルにこのヘッダー ファイルが含まれている場合は、マクロ名の有効範囲が制限されているため、エラーが発生します。はこの C ソース ファイルに限定されているため、これらの複数の C ファイルをコンパイルするときにエラーは発生しませんが、リンクするときに、同じ変数を複数の場所で定義したというエラーが報告されます。

Linking...
incl2 .obj : エラー LNK2005: "int glb" (?glb@@3HA) は incl1.obj
Debug/incl.exe ですでに定義されています : 致命的なエラー LNK1169: 1 つ以上の多重定義されたシンボルが見つかりました

注意! ! !

extern

このキーワードは本当に憎いです。宣言するとき、このexternは省略できるので、これが宣言なのか定義なのか混乱してしまいます。以下は、変数と関数の2つのカテゴリに分かれています:

( 1) 変数

特に変数について。
extern int a;//グローバル変数を宣言します a
int a; //グローバル変数を定義します a

extern int a =0;//グローバル変数 aを定義し、初期値を与えます。
int a =0;//グローバル変数 a を定義し、それに初期値を与えます。

4 番目の変数は 3 番目の変数と同じです。どちらも外部で使用できるグローバル変数を定義し、それに初期値を与えます。
混乱しているでしょう、彼らは本当に似ています。ただし、定義は 1 か所にのみ記述できます。つまり、int a; であろうと extern int a=0; であろうと int a=0; であろうと、それは 1 回しか出現できませんが、その extern int a は何度も出現することができます。

グローバル変数を参照したい場合は、 extern int a を宣言する必要があります。省略すると int a になるため、extern は省略できません。これは宣言ではなく定義です。

(2) 関数
関数、関数、関数も同様に定義して宣言します。宣言するときは、この関数が外部参照できることを示すために extern を使用します。声明。ただし、関数の定義と宣言には違いがあるため、定義された関数には関数本体が必要ですが、宣言された関数には関数本体がありません。そのため、関数の定義と宣言の際に extern を省略できます。他のファイルもこの関数が別の場所で定義されていることを認識しているため、 extern を追加しなくても大丈夫です。両者は大きく異なるため、extern を省略しても問題ありません。
例:

int fun(void)
{
return 0;
}

とても良いですね、グローバル関数

int fun(void);
を定義しました。それを宣言すると、次のようになります。
externの有無は関係ありません
ヘッダファイルにfunの宣言を入れることもでき、最終的にはこうなります

int fun(void);//関数宣言なのでexternは省略これは、より完全な extern int fun(void);

int fun(void)
{
return 0;
}//完全なグローバル関数定義。関数本体があるため、extern も省略されます。
次に、クライアント、あなたの楽しみを利用したいクライアントは、このヘッダー ファイル、わかりました、グローバル ステートメントをインクルードします。問題ない。
これに応じて、この顧客がグローバル変数を使用したい場合は、特定の変数を extern にする必要があり、そうでない場合は定義になります。

要約すると:

変数について、このソース ファイルで別のソース ファイルの変数を使用したい場合は、使用する前に extern で変数を宣言するか、ヘッダー ファイルで extern で変数を宣言する必要があります。関数の場合、このソース ファイル内で別のソース ファイルの関数を使用する場合は、extern で関数を宣言するかどうかは関係なく、使用する前に変数を宣言する必要があります。 extern をヘッダー ファイルの関数に追加します。


宣言は、各識別子のスペースを事前に保存せずに、各識別子の意味を説明するために使用されます。予約された記憶領域の宣言は定義と呼ばれます。宣言の形式は次のとおりです。 宣言指定子 宣言子 宣言子は、記憶クラス指定子と型指定子で構成されます。

1. 変数を宣言する場合は 2 つの状況があります。1 つはストレージ領域の作成が必要です。

例: int a は宣言時にすでにストレージスペースを作成しています。

2. もう一つは、収納スペースを作る必要がないことです。
例: extern int a 変数 a は別のファイルで定義されています。

例 1:

宣言。

属性を変数名または関数に関連付ける構造。例:
extrn int a;
extrn char c;
変数宣言 構造体の宣言は次のようになります。
Definition.
変数定義はストレージ割り当てを伴う宣言です。


struct per_rec

{

int age;

char *surname;
char *firstname;

};

int a;

char c;

struct per_rec person;



関数の名前、パラメータ、戻り値の型を指定する構造体。たとえば、関数定義は次のようになります。

long sqr(int num)

{

return(num*num) );

}


前者は「定義宣言」または「定義」であり、後者は「参照宣言」です。広い観点から見ると、宣言には定義が含まれますが、すべての宣言が定義であるわけではありません。たとえば、 int a は宣言と定義の両方です。ただし、extern a の場合、これは単なる宣言であり、定義ではありません。同じソース プログラム内または異なるソース プログラム内で繰り返し宣言できます。通常の状況では、スペースを作成するステートメントを「定義」と呼び、ストレージスペースの作成を必要としないステートメントを「宣言」と呼び、このように説明することがよくあります。明らかに、ここで言及しているステートメントは範囲が比較的狭い、つまり非定義ステートメントです。

例: main関数内



int main()

{

int a; //これは定義(領域確保の宣言)であり、繰り返し出現することはできません

// extern int a; と書くとor int here a; VC6.0 でコンパイルすると、重複した定義に対してエラーが報告されます

//(再定義)

//DEV-C++ でコンパイルするとエラーが報告されます (再宣言)
//DEV- でのコンパイルと実行には問題ありません。 C++
extern int A; //これは定義ではなく宣言です。宣言 A はすでに定義されている外部変数です
//注: extern A;
のように、外部変数を宣言するときに変数の型を削除できます。 dosth(); //関数を実行する
}
int A; //Aを整数型の外部変数として定義する定義です

定義や宣言が処理に関係する場合があるようですコンパイラの。

外部変数の「定義」は、外部変数の「宣言」とは異なります。外部変数の定義は 1 回のみであり、その場所はすべての関数の外にありますが、外部変数の宣言は同じ関数内で行われます。ファイルは複数回指定できます。関数内 (使用する関数はその関数内で宣言されます) または関数の外 (外部変数の定義ポイントの前) に置くことができます。システムは、(外部変数の宣言ではなく) 外部変数の定義に基づいて記憶域スペースを割り当てます。外部変数の場合、初期化は「宣言」ではなく「定義」でのみ行うことができます。
いわゆる「宣言」とは、その変数が後から定義された外部変数であることを宣言することであり、変数を「事前」に参照するために行われる「宣言」に過ぎません。 extern はステートメントを作成するだけで、定義は行いません。

static を使用した変数の宣言には 2 つの機能があります:
(1) ローカル変数が static として宣言される場合、変数に割り当てられた空間はプログラムの実行期間を通じて常に存在します。
(2) 外部変数が static として宣言されている場合、変数の役割はこのファイル モジュールに限定されます。

#include "stdafx.h"
1.extern は変数宣言でよく使用されます。このグローバル変数を参照する場合は、*.h に配置します。 externで宣言してください。
2. キーワード extern が関数宣言に含まれている場合、それは関数が他のソース ファイルで定義される可能性があることを意味するだけであり、他の効果はありません。つまり、次の 2 つの関数宣言には違いはありません:
extern int f() と int f();
================== === ===========
関数を定義する c/cpp ファイルが対応するヘッダー ファイルで定義された関数を宣言している場合、これらの関数を他の c/cpp ファイルで使用するには、インクルードする必要があるのは、このヘッダー ファイルだけで十分です。
ヘッダー ファイルをインクルードしたくない場合は、c/cpp で関数を宣言します。一般に、このファイルで定義された関数を宣言する場合は「extern」を使用せず、他のファイルで定義された関数を宣言する場合は「extern」を使用します。このように、他のファイルで定義された関数をこのファイルで呼び出す場合は、その必要はありません。ヘッダーファイルをインクルードするには
「*.h」をインクルードして関数を宣言すると、宣言後に直接使用できます。
==============================
例:
//extern。 cpp の内容は次のとおりです:

// extern.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"
extern print (char *p);
int main(int argc, char* argv[])
{
 char *p="hello world!";
 print(p);
 return 0;
}
//print.cppの内容は以下の通り
#include "stdafx.h"
#include "stdio.h"
print(char *s)
{
 printf("The string is %sn",s);
}
その結果、プログラムは正常に実行され、結果が出力されます。 「extern」を削除しても、プログラムは通常どおり実行できます。

「extern」は関数宣言では不要であることがわかります。これは、関数がこのファイルで定義されているか、別のファイルで定義されているかを示すためにのみ使用されます。関数が使用前に宣言されている限り、ヘッダー ファイルをインクルードする必要はありません。

C 言語では、修飾子 extern は変数または関数の宣言の前に使用され、「この変数/関数は別の場所で定義されているため、ここで参照する必要があります」ことを示します。

0. Extern は変数の宣言を変更します。たとえば、ファイル a.c が b.c の変数 int v を参照する必要がある場合、a.c で extern int v を宣言すると、変数 v を参照できます。ここで注意する必要があるのは、参照される変数 v のリンク属性は外部リンク (external) でなければならないということです。つまり、a.c が v を参照するには、a.c の extern int v の宣言だけではなく、ただし、変数 v 自体にも依存します。これには、C 言語の別のトピックである変数のスコープが関係します。 extern 修飾子を使用して他のモジュールから参照できる変数は、通常、グローバル変数です。もう 1 つの非常に重要な点は、extern int v を a.c のどこにでも配置できることです。たとえば、a.c の関数 fun の定義の先頭で extern int v を宣言すると、変数 v を参照できます。これですべてです。 v は関数 fun のスコープ内でのみ参照できますが、これは依然として変数スコープの問題です。この点に関しては、利用する際に不安を感じる人も多いでしょう。 extern ステートメントはファイル スコープでのみ使用できるようです。

1. extern 変更された関数宣言。基本的に、変数と関数に違いはありません。関数名は、関数のバイナリ ブロックの先頭へのポインタです。ファイル a.c が b.c の関数を参照する必要がある場合、たとえば、b.c のプロトタイプが int fun (int mu) である場合、a.c で extern int fun (int mu) を宣言すると、fun を使用して何でもできるようになります。変数の宣言と同様に、extern int fun (int mu) は a.c 内のどこにでも配置でき、必ずしも a.c のファイル スコープに配置する必要はありません。他のモジュールの関数を参照する最も一般的な方法は、それらの関数の宣言を含むヘッダー ファイルを使用することです。 extern を使用することと、関数を参照するためにヘッダー ファイルをインクルードすることの違いは何ですか? extern 参照方法は、ヘッダー ファイルをインクルードするよりもはるかに簡単です。 extern の使用は簡単です。extern を使用して、参照する関数を宣言します。これはおそらく KISS 原則の表れです。これを行うことの明白な利点は、プログラムのコンパイルのプロセス (正確には前処理) が高速化され、時間が節約されることです。この違いは、大規模な C プログラムをコンパイルするときに非常に明白です。

2. さらに、extern 修飾子を使用して、C または C++ 関数の呼び出し仕様を指定できます。たとえば、C++ で C ライブラリ関数を呼び出すには、extern "C" を使用して、C++ プログラム内で参照される関数を宣言する必要があります。これは、リンク時に C 関数仕様を使用するようにリンカに指示するためにリンカによって使用されます。主な理由は、C++ と C プログラムがコンパイルされた後のターゲット コードの命名規則が異なるためです



その他の extern 使用法まとめ関連記事については、PHP 中国語 Web サイトに注目してください。


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。