Storage-class specifiers
オブジェクトと関数の storage duration と linkage を指定します:
-
-
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 が配列型の関数パラメータで特別な意味を持つことに注意してください。
ストレージ期間
すべての object には storage duration と呼ばれる特性があり、これはobjectの lifetime を制限します。C言語には4種類のstorage durationがあります:
-
- automatic ストレージ期間。オブジェクトが宣言された ブロック に入ったときにストレージが割り当てられ、何らかの方法で( goto 、 return 、終端到達)ブロックを出たときに解放される。 例外は VLA であり、そのストレージはブロック進入時ではなく宣言が実行されたときに割り当てられ、ブロック終了時ではなく宣言がスコープ外に出たときに解放される (C99以降) 。ブロックが再帰的に進入された場合、各再帰レベルで新たな割り当てが行われる。全ての関数引数と非 static ブロックスコープオブジェクトはこのストレージ期間を持ち、 ブロックスコープで使用される 複合リテラル も同様 (C23以前)
- static ストレージ期間。ストレージ期間はプログラムの実行全体にわたり、オブジェクトに格納される値は main関数 の前に一度だけ初期化される。 static で宣言された全てのオブジェクトと、内部リンケージまたは外部リンケージを持つ全てのオブジェクト で _Thread_local (C23以前) thread_local (C23以降) で宣言されていないもの (C11以降) はこのストレージ期間を持つ。
|
(C11以降) |
-
- allocated ストレージ期間。ストレージは、 動的メモリ確保 関数を使用して要求に応じて割り当ておよび解放されます。
リンケージ
リンケージとは、識別子(変数または関数)が他のスコープから参照される能力を指します。同じ識別子を持つ変数または関数が複数のスコープで宣言されても、それらすべてから参照できない場合、変数の複数のインスタンスが生成されます。以下のリンケージが認識されます:
-
-
リンケージなし
。変数または関数は、それが存在するスコープ(ブロックスコープ)からのみ参照できます。
externとして宣言されていないすべてのブロックスコープ変数、およびすべての関数パラメータ、関数や変数ではないすべての識別子がこのリンケージを持ちます。
-
リンケージなし
。変数または関数は、それが存在するスコープ(ブロックスコープ)からのみ参照できます。
-
-
internal linkage
。変数または関数は、現在の翻訳単位内のすべてのスコープから参照できます。ファイルスコープの変数で
staticまたはconstexpr(C23以降) として宣言されたものはすべてこのリンケージを持ち、ファイルスコープの関数でstaticとして宣言されたもの(static関数宣言はファイルスコープでのみ許可されます)も同様です。
-
internal linkage
。変数または関数は、現在の翻訳単位内のすべてのスコープから参照できます。ファイルスコープの変数で
-
-
external linkage
。変数または関数はプログラム全体の他の翻訳単位から参照可能。ファイルスコープの変数で
staticが宣言されていないもの またはconstexprが宣言されていないもの (C23以降) はすべてこのリンケージを持つ。staticが宣言されていないすべてのファイルスコープ関数宣言、すべてのブロックスコープ関数宣言、さらにexternで宣言されたすべての変数または関数は、その時点で内部リンケージを持つ先行宣言が可視でない限り、このリンケージを持つ。
-
external linkage
。変数または関数はプログラム全体の他の翻訳単位から参照可能。ファイルスコープの変数で
同じ識別子が同じ翻訳単位内で内部リンケージと外部リンケージの両方で現れる場合、動作は未定義です。これは 暫定的な定義 が使用されている場合に発生する可能性があります。
リンケージとライブラリ
|
このセクションは不完全です
理由:これはC言語の「その他」カテゴリで独立したトップレベル項目とすべきか? |
外部リンケージを持つ宣言は、通常ヘッダーファイルで利用可能にされ、そのファイルを #include するすべての翻訳単位が、他の場所で定義されている同じ識別子を参照できるようにします。
内部リンケージを持つ宣言がヘッダーファイルに存在する場合、そのファイルをインクルードする各翻訳単位で個別のオブジェクトが生成されます。
ライブラリインターフェース、ヘッダーファイル "flib.h":
#ifndef FLIB_H #define FLIB_H void f(void); // 外部リンケージを持つ関数宣言 extern int state; // 外部リンケージを持つ変数宣言 static const int size = 5; // 内部リンケージを持つ読み取り専用変数の定義 enum { MAX = 10 }; // 定数定義 inline int sum (int a, int b) { return a + b; } // インライン関数定義 #endif // FLIB_H
ライブラリ実装、ソースファイル "flib.c":
#include "flib.h" static void local_f(int s) {} // 内部リンケージを持つ定義(このファイル内でのみ使用) static int local_state; // 内部リンケージを持つ定義(このファイル内でのみ使用) int state; // 外部リンケージを持つ定義(main.cで使用) void f(void) { local_f(state); } // 外部リンケージを持つ定義(main.cで使用)
アプリケーションコード、ソースファイル「main.c」:
#include "flib.h" int main(void) { int x[MAX] = {size}; // 定数と読み取り専用変数を使用 state = 7; // flib.c内のstateを変更 f(); // flib.c内のf()を呼び出し }
キーワード
auto , register , static , extern , _Thread_local thread_local
注記
|
キーワード _Thread_local は通常、ヘッダー <threads.h> で定義される便利マクロ thread_local を通じて使用されます。 |
(C23まで) |
C言語の文法では、
typedef
および
constexpr
(C23以降)
指定子は形式的に記憶クラス指定子として分類されていますが、実際には記憶域を指定するものではありません。
|
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++ ドキュメント
for
Storage class specifiers
|