ストレージクラス指定子
オブジェクトと関数のストレージ期間およびリンケージを指定します
auto- 自動期間、リンケージなしregister- 自動期間、リンケージなし。この変数のアドレスを取ることはできませんstatic- 静的期間、内部リンケージ(ブロックスコープでない場合)extern- 静的期間、外部リンケージ(既に内部リンケージとして宣言されていない場合)
|
(C11 以降) |
目次 |
[編集] 説明
ストレージクラス指定子は宣言および複合リテラル式(C23以降)に現れます。指定子は最大1つまで使用できますが、_Thread_local(C23まで)thread_local(C23以降)はstaticまたはexternと組み合わせてリンケージを調整できます(C11以降)。ストレージクラス指定子は、それらが宣言する名前の2つの独立したプロパティ、すなわちストレージ期間とリンケージを決定します。
_Alignas(C23まで)alignas(C23以降)を使用できません(C11以降)。また、register配列はポインタに変換できません。|
5) _Thread_local(C23まで)thread_local(C23以降)はスレッドストレージ期間を示します。関数宣言には使用できません。オブジェクトの宣言に使用される場合、同じオブジェクトのすべての宣言で存在する必要があります。ブロックスコープ宣言に使用される場合、リンケージを決定するためにstaticまたはexternのいずれかと組み合わせる必要があります。 |
(C11 以降) |
ストレージクラス指定子が提供されない場合、デフォルトは次のようになります
- すべての関数に対してextern
- ファイルスコープのオブジェクトに対してextern
- ブロックスコープのオブジェクトに対してauto
ストレージクラス指定子で宣言された構造体または共用体のメンバーには、再帰的に、そのストレージ期間(ただしリンケージではない)が適用されます。
ブロックスコープの関数宣言にはexternを使用するか、何も使用しないかのいずれかです。ファイルスコープの関数宣言にはexternまたはstaticを使用できます。
関数パラメータには、register以外のストレージクラス指定子を使用することはできません。配列型の関数パラメータにおけるstaticは特別な意味を持つことに注意してください。
[編集] ストレージ期間
すべてのオブジェクトには、オブジェクトの寿命を制限するストレージ期間というプロパティがあります。Cには4種類のストレージ期間があります
- 自動ストレージ期間。ストレージは、オブジェクトが宣言されたブロックに入るときに割り当てられ、goto、return、またはブロックの終了によって、ブロックを終了するときに解放されます。 C99以降の例外はVLAで、そのストレージはブロックエントリ時ではなく宣言が実行されたときに割り当てられ、ブロック終了時ではなく宣言がスコープを外れたときに解放されます。ブロックが再帰的に入力された場合、各再帰レベルで新しい割り当てが行われます。すべての関数パラメータと非staticブロックスコープオブジェクトは、このストレージ期間を持ちます。C23までの複合リテラルも同様です。
- 静的ストレージ期間。ストレージ期間はプログラムの実行全体であり、オブジェクトに格納される値は、main関数の前に一度だけ初期化されます。すべてstaticとして宣言されたオブジェクト、および内部または外部リンケージを持つすべてのオブジェクト(C11以降、_Thread_local(C23まで)thread_local(C23以降)として宣言されていないもの)は、このストレージ期間を持ちます。
|
(C11 以降) |
- 割り当て済みストレージ期間。ストレージは、動的メモリ割り当て関数を使用して、要求に応じて割り当ておよび解放されます。
[編集] リンケージ
リンケージは、識別子(変数または関数)が他のスコープで参照される能力を指します。同じ識別子を持つ変数または関数が複数のスコープで宣言されているが、それらすべてから参照できない場合、その変数の複数のインスタンスが生成されます。以下のリンケージが認識されます
- リンケージなし。変数または関数は、それが属するスコープ(ブロックスコープ)からのみ参照できます。
externとして宣言されていないすべてのブロックスコープ変数、およびすべての関数パラメータと、関数または変数でないすべての識別子は、このリンケージを持ちます。
- リンケージなし。変数または関数は、それが属するスコープ(ブロックスコープ)からのみ参照できます。
- 内部リンケージ。変数または関数は、現在の翻訳単位内のすべてのスコープから参照できます。
staticまたはconstexpr(C23以降)として宣言されたすべてのファイルスコープ変数、およびstaticとして宣言されたすべてのファイルスコープ関数(static関数宣言はファイルスコープでのみ許可されます)は、このリンケージを持ちます。
- 内部リンケージ。変数または関数は、現在の翻訳単位内のすべてのスコープから参照できます。
- 外部リンケージ。変数または関数は、プログラム全体の他のどの翻訳単位からでも参照できます。
staticまたはconstexpr(C23以降)として宣言されていないすべてのファイルスコープ変数、staticとして宣言されていないすべてのファイルスコープ関数宣言、すべてのブロックスコープ関数宣言、さらに、externとして宣言されたすべての変数または関数は、その時点で内部リンケージを持つ前の宣言が可視でない限り、このリンケージを持ちます。
- 外部リンケージ。変数または関数は、プログラム全体の他のどの翻訳単位からでも参照できます。
同じ識別子が同じ翻訳単位内で内部リンケージと外部リンケージの両方で現れる場合、動作は未定義です。これは、暫定定義が使用される場合に可能です。
[編集] リンケージとライブラリ
| このセクションは未完成です 理由: これはc/languageのMiscellaneousの下に別個のトップレベルエントリであるべきですか? |
外部リンケージを持つ宣言は、一般的にヘッダーファイルで利用可能になり、ファイルを含めるすべての翻訳単位が、他の場所で定義されているのと同じ識別子を参照できるようにします。
ヘッダーファイルに出現する内部リンケージを持つ宣言は、そのファイルを含める各翻訳単位に別個の、区別されたオブジェクトをもたらします。
|
ライブラリインターフェース、ヘッダーファイル "flib.h" #ifndef FLIB_H #define FLIB_H void f(void); // function declaration with external linkage extern int state; // variable declaration with external linkage static const int size = 5; // definition of a read-only variable with internal linkage enum { MAX = 10 }; // constant definition inline int sum (int a, int b) { return a + b; } // inline function definition #endif // FLIB_H ライブラリ実装、ソースファイル "flib.c" #include "flib.h" static void local_f(int s) {} // definition with internal linkage (only used in this file) static int local_state; // definition with internal linkage (only used in this file) int state; // definition with external linkage (used by main.c) void f(void) { local_f(state); } // definition with external linkage (used by main.c) アプリケーションコード、ソースファイル "main.c" #include "flib.h" int main(void) { int x[MAX] = {size}; // uses the constant and the read-only variable state = 7; // modifies state in flib.c f(); // calls f() in flib.c } |
[編集] キーワード
auto、register、static、extern、_Thread_local thread_local
[編集] 注記
|
キーワード_Thread_localは、通常、ヘッダー<threads.h>で定義されている便利なマクロthread_localを通じて使用されます。 |
(C23まで) |
typedefおよびconstexpr(C23以降)指定子は、C言語の文法では正式にストレージクラス指定子としてリストされていますが、ストレージを指定しません。
|
auto指定子は、型推論にも使用されます。 |
(C23以降) |
ファイルスコープの名前でconstであり、externでないものは、Cでは外部リンケージ(すべてのファイルスコープ宣言のデフォルトとして)を持ちますが、C++では内部リンケージを持ちます。
[編集] 例
#include <stdio.h> #include <stdlib.h> // static storage duration int A; int main(void) { printf("&A = %p\n", (void*)&A); // automatic storage duration int A = 1; // hides global A printf("&A = %p\n", (void*)&A); // allocated storage duration int* ptr_1 = malloc(sizeof(int)); // start allocated storage duration printf("address of int in allocated memory = %p\n", (void*)ptr_1); free(ptr_1); // stop allocated storage duration }
実行結果の例
&A = 0x600ae4 &A = 0x7ffefb064f5c address of int in allocated memory = 0x1f28c30
[編集] 参考文献
- C23標準 (ISO/IEC 9899:2024)
- 6.2.2 識別子のリンケージ (p: 35-36)
- 6.2.4 オブジェクトのストレージ期間 (p: 36-37)
- 6.7.1 ストレージクラス指定子 (p: 97-100)
- C17標準 (ISO/IEC 9899:2018)
- 6.2.2 識別子のリンケージ (p: 29-30)
- 6.2.4 オブジェクトのストレージ期間 (p: 30)
- 6.7.1 ストレージクラス指定子 (p: 79)
- C11標準 (ISO/IEC 9899:2011)
- 6.2.2 識別子のリンケージ (p: 36-37)
- 6.2.4 オブジェクトのストレージ期間 (p: 38-39)
- 6.7.1 ストレージクラス指定子 (p: 109-110)
- C99標準 (ISO/IEC 9899:1999)
- 6.2.2 識別子のリンケージ (p: 30-31)
- 6.2.4 オブジェクトのストレージ期間 (p: 32)
- 6.7.1 ストレージクラス指定子 (p: 98-99)
- C89/C90標準 (ISO/IEC 9899:1990)
- 3.1.2.2 識別子のリンケージ
- 3.1.2.4 オブジェクトのストレージ期間
- 3.5.1 ストレージクラス指定子
[編集] 関連項目
| C++ドキュメント (ストレージクラス指定子)
|