C/C++外部リンクの静的変数


外部リンクの静的変数には、ファイルの役割ドメイン、外部リンク、および静的ストレージ期間があります.
このカテゴリは、外部ストレージカテゴリ(external storage class)と呼ばれる場合があり、そのカテゴリに属する変数を外部変数(external variable)と呼ぶ.変数の定義宣言(defining declaration)をすべての関数の外に置くと外部変数が作成されます.もちろん、この関数が外部変数を使用していることを示すために、関数でキーワードexternで再宣言することができます.あるソースファイルで使用される外部変数が別のソースファイルで定義されている場合は、externで変数を宣言する必要があります.次のようになります.
int Errupt;        /*         */
double Up[100];      /*         */
extern char Coal;     /*   Coal         , */
/*       */
void next(void);
int main(void)
{
extern int Errupt;   /*      */
extern double Up[];  /*      */
...

}
void next(void)
{
...
}

ただし、main()でUp配列を宣言する場合(オプションの宣言)は、配列サイズ情報が1回目の宣言で提供されているため、配列サイズを指定する必要はありません.main()の2つのextern宣言は完全に省略できます.外部変数にはファイルの役割ドメインがあるため、ErruptとUpは宣言からファイルの最後まで表示されます.main()関数を説明するためにこの2つの変数を使用します.関数のexternキーを省略すると、自動変数が作成されることになります.次の宣言のexternを削除します.
extern int Errupt;

次のようになります.
int Errupt;

これにより、コンパイラはmain()にErruptという自動変数を作成します.元の外部変数Erruptとは異なる独立した局所変数である.ローカル変数はmain()にのみ表示されますが、外部変数Erruptは、next()などのファイルの他の関数にも表示されます.簡単に言えば、ブロック内の文を実行すると、ブロックの役割ドメイン内の変数がファイルの役割ドメイン内の同じ名前の変数を「非表示」にします.外部変数と同じ名前のローカル変数を使用する必要がある場合は、ローカル変数の宣言でautoストレージカテゴリ説明子を使用して、この意図を明確に表現できます.外部変数には静的ストレージ期間があります.したがって、プログラムがmain()、next()または他の関数に実行されても、配列Upおよびその値は常に存在する.
次の3つの例では、外部変数と自動変数の使用例を示します.例1に外部変数Hocusがあります.この変数はmain()とmagic()の両方に表示されます.
/*   1 */
int Hocus;
int magic();
int main(void)
{
extern int Hocus; // Hocus           
...
}
int magic()
{
extern int Hocus; //     Hocus       
...
}

例2には外部変数Hocusがあり、両方の関数に対して表示されます.今回は、デフォルトでmagic()が表示されます.
/*  2 */
int Hocus;
int magic();
int main(void)
{
extern int Hocus; // Hocus          
...
}
int magic()
{
//         Hocus,         
...
}

例3では、4つの独立した変数が作成されている.main()のHocus変数のデフォルトは自動変数であり、main()プライベートに属します.magic()のHocus変数は明示的に自動として宣言され、magic()のみが使用可能である.外部変数Houcusはmain()とmagic()には表示されませんが、ファイルにローカルHocus変数が作成されていない他の関数には表示されます.最後に、Pocusは外部変数であり、magic()は表示されますが、main()は表示されません.Pocusはmain()の後ろに宣言されているためです.
/*    3 */
int Hocus;
int magic();
int main(void)
{
int Hocus; //   Hocus,       
...
}
int Pocus;
int magic()
{
auto int Hocus; //     Hocus         
...
}

この3つの例では、外部変数の役割ドメインを宣言からファイルの最後まで示します.このほか,外部変数のライフサイクルについても説明した.外部変数HocusとPocusは、どの関数にも制限されず、ある関数が戻った後に消えることはないため、プログラムの実行中に常に存在します.
  • 初期化外部変数外部変数は、自動変数と同様に、明示的に初期化することもできる.自動変数とは異なり、外部変数が初期化されていない場合、自動的に0に初期化されます.この原則は、外部で定義された配列要素にも適用されます.自動変数の場合とは異なり、定数式を使用してファイルの役割ドメイン変数を初期化するしかありません:int x=10;//大丈夫です.10は定数int y=3+20です.//大丈夫です.初期化に使用する定数式size_t z = sizeof(int);//大丈夫です.初期化に使用する定数式int x 2=2*xです.//いいえ、xは変数です(変長配列でなければsizeof式は定数式と見なすことができます).
  • 外部変数を使用する外部変数の例を次に示す.変数unitsにアクセスする2つの関数main()とcritic()があるとします.プログラムに示すようにunitsをこの2つの関数に宣言することができます(注意:この例の目的は外部変数の動作原理を実証することであり、その典型的な使い方ではありません).
  • /* global.c --        */
    #include 
    int units = 0;    /*      */
    void critic(void);
    int main(void)
    {
    extern int units; /*         */
    printf("How many pounds to a firkin of butter?
    "
    ); scanf("%d", &units); while (units != 56) critic(); printf("You must have looked it up!
    "
    ); return 0; } void critic(void) { /* */ printf("No luck, my friend. Try again.
    "
    ); scanf("%d", &units); } : How many pounds to a firkin of butter? 14 No luck, my friend. Try again. 56 You must have looked it up!

    注意critic()はunitsの2番目の値をどのように読み出すかです.whileループが終了するとmain()もunitsの新しい値を知っています.したがってmain()関数とcritic()は、同じ変数に識別子unitsでアクセスできます.Cの用語で説明すると、unitsはファイルの役割ドメイン、外部リンク、および静的記憶期間を有する.unitsをすべての関数定義の外(すなわち外部)に定義すると、unitsは外部変数であり、units定義の下のすべての関数に表示されます.したがって、critics()はunits変数を直接使用することができる.同様にmain()もunitsに直接アクセスできます.ただし、main()には確かに次のような声明があります.
    extern int units;
    

    この例では、上記の宣言は、主にこの関数がこの外部変数を使用することを示すためです.ストレージカテゴリ説明子externは、unitsを使用する場所で同じ関数の外部に定義された変数を参照するコンパイラに伝えます.main()とcritic()は、外部定義のunitsを使用していることを改めて強調します.
    3.外部名C 99およびC 11の規格は、コンパイラがローカル識別子の最初の63文字および最初の31文字を識別することを要求する.これは、コンパイラがローカル識別子の最初の31文字と外部識別子の前の6文字を識別する以前の基準を改訂した.あなたが使っているコンパイラは、以前のルールも実行する可能性があります.外部変数名は、ローカル変数名のルールよりも厳格です.外部変数名はローカル環境ルールに従うため、より制限されています.4.定義と宣言変数の定義と宣言変数の違いについて説明します.次の例を考えます.
    int tern = 1; /* tern    */
    main()
    {
    extern int tern; /*         tern */
    

    ここでternは2回宣言された.1回目の宣言は、変数の定義を構成する変数が格納空間を予約したものである.2回目の宣言は、コンパイラが以前に作成したtern変数を使用することを示すだけで、定義ではありません.1回目の宣言は定義式宣言(defining declaration)と呼ばれ、2回目の宣言は参照式宣言(referenceng declaration)と呼ばれます.キーワードexternは、コンパイラが定義を別の場所でクエリーするように指示するため、宣言が定義されていないことを示します.このように書くとします.
    extern int tern;
    int main(void)
    {
    

    コンパイラはternの実際の定義がプログラムの他の場所にあると仮定し、他のファイルにあるかもしれません.この宣言は、ストレージ領域の割り当てを引き起こすことはありません.したがって、キーワードexternで外部定義を作成するのではなく、既存の外部定義を参照するために使用します.外部変数は一度だけ初期化でき、その変数を定義するときに行う必要があります.次のコードがあるとします.
    // file_one.c
    char permis = 'N';
    ...
    // file_two.c
    extern char permis = 'Y'; /*    */
    

    file_twoの宣言は間違っています.file_のためです.one.cの定義式宣言はpermisを作成し初期化した.