C言語の記憶類説明子
8291 ワード
役割ドメインリンク属性格納時期格納タイプ内容はまずブログを参照してください
C言語には5種類の修飾子が格納されている: staticコードブロックの役割ドメインを有する変数の宣言に用いる場合には、その変数に静的記憶タイプ(静的メモリに格納)を持たせる. staticは、ファイルの役割ドメインを有する識別子(変数名、関数名)に用いる場合、その識別子が内部リンク属性を有することを示す.
.
次の文がすべての関数体の外に表示されている場合 に実行する. に初期化する. を有するだけである. を指す.
次の文が関数内に表示されている場合 にアクセスする. に初期化する. が生じる.
プログラム1コンパイルパス..
プログラム2はwin 7+VS 2015プラットフォームの下でエラーを報告します:error LNK 2001:解析できない外部記号_i
プログラム3はwin 7+VS 2015プラットフォームの下でエラーを報告します:error C 2065:“i”:宣言されていない識別子
プログラム4のコンパイルに成功し、1を印刷した.
プログラム5 win 7+VS 2015でerror C 2086:“int i”:再定義
プログラム6 win 7+VS 2015でerror C 2086:“int i”:再定義
プログラム7のコンパイルにより、1を印刷する.
上記の例を総合すると、コンパイラ時にまずiが定義されているか否か(メモリが存在する)を判断し、定義されていない場合は
以上externの使い方については個人的な推測にすぎません
ストレージ・クラス・ディスクリプタについては、次の点を説明します.宣言には、最大1つのストレージクラス説明子 しかありません.クラス説明子が識別子を変更できない役割ドメイン を格納する. である.は、 として扱われる. がある.
C言語には5種類の修飾子が格納されている:
auto
register
static
extern
typedef
以下に各説明子の使い方を紹介する.auto
:変数が自動記憶タイプautoを有することを示す説明子は、コードブロックの役割ドメインを有する変数の宣言にのみ使用できるが、これらの変数自体が自動記憶タイプ(ランタイムスタックに格納)を有するため、autoは通常、明示的な説明の役割を果たすだけである.register
:変数がハードウェアレジスタを有することを示す格納タイプregisterも、コードブロックの役割ドメインを有する変数の宣言にのみ用いることができ、プログラマがCPUのレジスタにこの変数を置くことを望んでいることを示し、通常の変数よりも早く変数にアクセスして操作することができる.ただし、レジスタの格納タイプの変数のアドレスを取得することができず、registerが宣言する変数をレジスタに格納するか否かはコンパイラによって決定される.static
:変数が静的ストレージタイプを有するか、識別子が内部リンク属性を有することを示すextern
:識別子が外部リンク属性を有することを示すか、またはその変数がexternの使用を理解するために他の場所で定義されていることを示す.まずC言語の宣言と定義の違いを理解する.宣言:記述プログラムの他の場所で定義されたオブジェクト定義:オブジェクトにメモリを割り当てる次の文がすべての関数体の外に表示されている場合
int i;
はint型変数を定義し、メモリを割り当て、デフォルトの初期化を0 int i = 1;
はint型変数を定義し、メモリを割り当て、1 extern int i = 1;
はint型変数を定義し、メモリを割り当て、1に初期化する.識別子iはファイルの役割ドメインを有するため、デフォルトでは外部リンク属性を有するが、externの役割は明示的な説明識別子iが外部リンク属性extern int i;
は変数iがint型であることを記述し、プログラムの他の場所で定義(メモリの割り当て)され、ここで他の場所は現在のコンパイルユニット(同じソースファイル)または他のコンパイルユニット(他のソースファイル)を含む.zはextern宣言と呼ぶことができ、外部リンク属性を有する識別子は複数のソースファイルで使用することができ、同じエンティティ// main.c
#include
extern int i; // i extern
int main(void)
{
int i = 1; // i
printf("%d", i);
return 0;
}
// main.c
#include
extern int i; // i extern
int main(void)
{
printf("%d", i);
return 0;
}
// define.c
int i = 1; // i
次の文が関数内に表示されている場合
int i;
はint型変数を定義し、メモリを割り当てるが、初期化は実行されず、iの値はランダムであり、この変数に不正なint i = 1;
はint型変数を定義し、メモリを割り当て、1 extern int i = 1;
この文は、同様にint変数iを定義しようとする、識別子iを外部リンク属性に設定しようとするが、C言語では関数内部で外部変数を初期化できないことが規定するため、この文は不正である.では、関数の外部で文int i = 0
を使用して定義して初期化し、extern int i = 1
を付与操作と見なしますか?関数外部のint i = 0
はiの定義であるため、関数内部のextern int i = 1
もiの定義であり、これによりiの繰返し定義エラーextern int i;
この文は関数体の内部に置くと複雑で、いくつかの例を挙げる.// program 1
// main.c
#include
int main(void)
{
extern int i;
return 0;
}
プログラム1コンパイルパス..
// program 2
// main.c
#include
int main(void)
{
extern int i;
printf("%d", i);
return 0;
}
プログラム2はwin 7+VS 2015プラットフォームの下でエラーを報告します:error LNK 2001:解析できない外部記号_i
// program 3
// main.c
#include
int main(void)
{
printf("%d", i);
return 0;
}
プログラム3はwin 7+VS 2015プラットフォームの下でエラーを報告します:error C 2065:“i”:宣言されていない識別子
// program 4
// main.c
#include
int i = 1;
int main(void)
{
extern int i;
printf("%d", i);
return 0;
}
プログラム4のコンパイルに成功し、1を印刷した.
// program 5
// main.c
#include
int main(void)
{
int i = 1;
extern int i;
return 0;
}
プログラム5 win 7+VS 2015でerror C 2086:“int i”:再定義
// program 6
// main.c
#include
int main(void)
{
extern int i;
int i = 1;
return 0;
}
プログラム6 win 7+VS 2015でerror C 2086:“int i”:再定義
// program 7
// main.c
#include
int main(void)
{
extern int i;
printf("%d", i);
return 0;
}
// define.c
int i = 1;
プログラム7のコンパイルにより、1を印刷する.
上記の例を総合すると、コンパイラ時にまずiが定義されているか否か(メモリが存在する)を判断し、定義されていない場合は
extern int i;
をiに対するextern宣言とする.iの定義がある場合はiのリンク性を判断し、外部リンクであればextern int i;
をiのextern宣言とし、iが無リンク属性であればextern int i
をiに対する定義とし、externを用いるiを外部リンク属性と強制する(初期値が付与されていないため関数内部で外部変数を初期化できないエラーは発生しない)、これにより2つのiの定義があるため、エラーを報告して繰り返し定義する.以上externの使い方については個人的な推測にすぎません
typedef
typedef説明子は、オブジェクトのために記憶空間を予約することはなく、それを記憶クラス説明子に分類するのは、文法記述の便利さのためである.ストレージ・クラス・ディスクリプタについては、次の点を説明します.
static
は、記憶タイプを変更するためにもリンク属性を変更するためにも使用することができ、具体的にどのような役割を果たすかは、その修飾識別子の役割ドメインによって決定されるextern
によって修飾する識別子が外部リンク属性を有する場合にのみextern宣言register
修飾変数は実際にレジスタに格納かどうかコンパイラ決定