名前空間
変種
操作

ストレージクラス指定子

From cppreference.com
< c‎ | language

オブジェクトと関数のストレージ期間およびリンケージを指定します

  • auto - 自動期間、リンケージなし
  • register - 自動期間、リンケージなし。この変数のアドレスを取ることはできません
  • static - 静的期間、内部リンケージ(ブロックスコープでない場合)
  • extern - 静的期間、外部リンケージ(既に内部リンケージとして宣言されていない場合)
  • _Thread_local(C23まで)thread_local(C23以降) - スレッドストレージ期間
(C11 以降)

目次

[編集] 説明

ストレージクラス指定子は宣言および複合リテラル(C23以降)に現れます。指定子は最大1つまで使用できますが、_Thread_local(C23まで)thread_local(C23以降)staticまたはexternと組み合わせてリンケージを調整できます(C11以降)。ストレージクラス指定子は、それらが宣言する名前の2つの独立したプロパティ、すなわちストレージ期間リンケージを決定します。

1) auto指定子は、ブロックスコープ(関数パラメータリストを除く)で宣言されたオブジェクトにのみ許可されます。これは、これらの宣言のデフォルトである自動ストレージ期間とリンケージなしを示します。
2) register指定子は、関数パラメータリストを含むブロックスコープで宣言されたオブジェクトにのみ許可されます。これは、自動ストレージ期間とリンケージなし(これらの宣言のデフォルト)を示しますが、さらに最適化プログラムに可能であればこの変数の値をCPUレジスタに格納するようにヒントを与えます。この最適化が行われるかどうかにかかわらず、registerとして宣言された変数は、アドレス演算子の引数として使用できません_Alignas(C23まで)alignas(C23以降)を使用できません(C11以降)。また、register配列はポインタに変換できません。
3) static指定子は、静的ストレージ期間_Thread_localと組み合わされていない場合)(C11以降)と内部リンケージ(ブロックスコープで使用されない場合)の両方を指定します。これは、ファイルスコープの関数と、ファイルスコープおよびブロックスコープの両方の変数に使用できますが、関数パラメータリストには使用できません。
4) extern指定子は、静的ストレージ期間_Thread_local(C23まで)thread_local(C23以降)と組み合わされていない場合)(C11以降)と外部リンケージを指定します。これは、ファイルスコープとブロックスコープの両方の関数およびオブジェクト宣言(関数パラメータリストを除く)に使用できます。もしexternが、既に内部リンケージで宣言されていた識別子の再宣言に現れる場合、リンケージは内部のままです。それ以外の場合(前の宣言が外部、リンケージなし、またはスコープ外だった場合)、リンケージは外部になります。
5) _Thread_local(C23まで)thread_local(C23以降)スレッドストレージ期間を示します。関数宣言には使用できません。オブジェクトの宣言に使用される場合、同じオブジェクトのすべての宣言で存在する必要があります。ブロックスコープ宣言に使用される場合、リンケージを決定するためにstaticまたはexternのいずれかと組み合わせる必要があります。
(C11 以降)

ストレージクラス指定子が提供されない場合、デフォルトは次のようになります

すべての関数に対してextern
ファイルスコープのオブジェクトに対してextern
ブロックスコープのオブジェクトに対してauto

ストレージクラス指定子で宣言された構造体または共用体のメンバーには、再帰的に、そのストレージ期間(ただしリンケージではない)が適用されます。

ブロックスコープの関数宣言にはexternを使用するか、何も使用しないかのいずれかです。ファイルスコープの関数宣言にはexternまたはstaticを使用できます。

関数パラメータには、register以外のストレージクラス指定子を使用することはできません。配列型の関数パラメータにおけるstaticは特別な意味を持つことに注意してください。

[編集] ストレージ期間

すべてのオブジェクトには、オブジェクトの寿命を制限するストレージ期間というプロパティがあります。Cには4種類のストレージ期間があります

  • 自動ストレージ期間。ストレージは、オブジェクトが宣言されたブロックに入るときに割り当てられ、gotoreturn、またはブロックの終了によって、ブロックを終了するときに解放されます。 C99以降の例外はVLAで、そのストレージはブロックエントリ時ではなく宣言が実行されたときに割り当てられ、ブロック終了時ではなく宣言がスコープを外れたときに解放されます。ブロックが再帰的に入力された場合、各再帰レベルで新しい割り当てが行われます。すべての関数パラメータと非staticブロックスコープオブジェクトは、このストレージ期間を持ちます。C23までの複合リテラルも同様です。
  • 静的ストレージ期間。ストレージ期間はプログラムの実行全体であり、オブジェクトに格納される値は、main関数の前に一度だけ初期化されます。すべてstaticとして宣言されたオブジェクト、および内部または外部リンケージを持つすべてのオブジェクト(C11以降、_Thread_local(C23まで)thread_local(C23以降)として宣言されていないもの)は、このストレージ期間を持ちます。
  • スレッドストレージ期間。ストレージ期間は、それが作成されたスレッドの実行全体であり、オブジェクトに格納される値は、スレッドが開始されたときに初期化されます。各スレッドは、独自の、区別されたオブジェクトを持ちます。このオブジェクトにアクセスする式を実行するスレッドが、その初期化を実行したスレッドでない場合、動作は実装定義です。すべて(C23まで)_Thread_local(C23まで)thread_local(C23以降)として宣言されたオブジェクトは、このストレージ期間を持ちます。
(C11 以降)
  • 割り当て済みストレージ期間。ストレージは、動的メモリ割り当て関数を使用して、要求に応じて割り当ておよび解放されます。

[編集] リンケージ

リンケージは、識別子(変数または関数)が他のスコープで参照される能力を指します。同じ識別子を持つ変数または関数が複数のスコープで宣言されているが、それらすべてから参照できない場合、その変数の複数のインスタンスが生成されます。以下のリンケージが認識されます

  • リンケージなし。変数または関数は、それが属するスコープ(ブロックスコープ)からのみ参照できます。externとして宣言されていないすべてのブロックスコープ変数、およびすべての関数パラメータと、関数または変数でないすべての識別子は、このリンケージを持ちます。
  • 内部リンケージ。変数または関数は、現在の翻訳単位内のすべてのスコープから参照できます。staticまたはconstexpr(C23以降)として宣言されたすべてのファイルスコープ変数、およびstaticとして宣言されたすべてのファイルスコープ関数(static関数宣言はファイルスコープでのみ許可されます)は、このリンケージを持ちます。
  • 外部リンケージ。変数または関数は、プログラム全体の他のどの翻訳単位からでも参照できます。staticまたはconstexpr(C23以降)として宣言されていないすべてのファイルスコープ変数、staticとして宣言されていないすべてのファイルスコープ関数宣言、すべてのブロックスコープ関数宣言、さらに、externとして宣言されたすべての変数または関数は、その時点で内部リンケージを持つ前の宣言が可視でない限り、このリンケージを持ちます。

同じ識別子が同じ翻訳単位内で内部リンケージと外部リンケージの両方で現れる場合、動作は未定義です。これは、暫定定義が使用される場合に可能です。

[編集] リンケージとライブラリ

外部リンケージを持つ宣言は、一般的にヘッダーファイルで利用可能になり、ファイルを含めるすべての翻訳単位が、他の場所で定義されているのと同じ識別子を参照できるようにします。

ヘッダーファイルに出現する内部リンケージを持つ宣言は、そのファイルを含める各翻訳単位に別個の、区別されたオブジェクトをもたらします。

ライブラリインターフェース、ヘッダーファイル "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
}

[編集] キーワード

autoregisterstaticextern_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++ドキュメントストレージクラス指定子
English 日本語 中文(简体) 中文(繁體)