C言語ストレージクラス完全理解:スコープ・ライフタイム・パフォーマンス
C言語ストレージクラス完全理解
自動、外部、静的、レジスタストレージクラスがC言語で変数のスコープ、ライフタイム、パフォーマンスをどう定義するかを探ります。
自動(ローカル)変数
ブロック内で宣言された変数は自動変数、つまりローカル変数です。そのブロック内でのみ存在し、ブロックが終わると破棄されます。
#include <stdio.h>
int main(void) {
for (int i = 0; i < 5; ++i) {
printf("C programming\n");
}
// エラー: iはこのスコープで宣言されていない
printf("%d", i);
return 0;
}
このプログラムを実行すると、iがforループブロック内でのみ宣言されているためundeclared identifier iエラーになります。
int main() {
int n1; // main()ローカル
}
void func() {
int n2; // func()ローカル
}
ここではn1はfunc()内でアクセス不可、n2はmain()内でアクセス不可です。
グローバル(外部)変数
すべての関数の外部で宣言された変数はグローバルまたは外部変数です。同じ翻訳単位内のあらゆる関数からアクセスできます。あるファイルで定義されたグローバル変数を別のファイルで使う場合、externキーワードで定義が別場所にあることを伝えます。
例: グローバル変数
#include <stdio.h>
void display();
int n = 5; // グローバル変数
int main() {
++n;
display();
return 0;
}
void display() {
++n;
printf("n = %d\n", n);
}
出力
n = 7
nがfile1.cで定義されfile2.cで使われる場合、file2.cの先頭にextern int n;を追加してコンパイルエラーを防ぎます。
レジスタ変数
registerキーワードは、コンパイラに変数をCPUレジスタに格納してアクセスを高速化するようヒントを与えます。現代のコンパイラは積極的な最適化を行うため、このヒントは多くの場合不要です。プロファイリングで組み込みシステムのクリティカルなボトルネックが判明した場合のみregisterを使用してください。
静的変数
静的変数はstaticで宣言され、プログラム実行中ずっと値を保持します。プログラム起動時に一度だけ初期化され、プログラム終了まで存在し続けます。
例: 静的変数
#include <stdio.h>
void display();
int main() {
display();
display();
}
void display() {
static int c = 1;
c += 5;
printf("%d ", c);
}
出力
6 11
初回呼び出し時、cは1で初期化され5増えて6になります。2回目呼び出し時、cは前回の値6を保持し、5増えて11になって表示されます。
ファイルスコープでstatic宣言すると、その変数は内部リンケージを持ち、他の翻訳単位から不可視になります。これはカプセル化に有用な機能です。
ISO C標準によれば、staticの振る舞いはすべての関数呼び出しで単一インスタンスを保証し、グローバル汚染なしでステートフルな操作を行う上で重要です。
C言語
- C# 変数とプリミティブデータ型:完全マスターガイド
- C# 変数のスコープを理解する:クラス、メソッド、ブロックレベル
- C# static キーワード:静的変数、メソッド、クラスをマスターする
- C++クラステンプレート完全ガイド:実践的なジェネリックプログラミング
- C言語変数・定数・リテラル完全ガイド
- C++変数とデータ型:int、double、char、string、boolを徹底解説
- C言語の変数を理解する:型、命名規則、メモリ管理
- C言語のストレージクラス:スコープ、ライフタイム、使い分け
- C言語のスコープルール:ローカル、グローバル、仮パラメータの理解
- C言語ポインタ完全マスター:実践的ステップで上級プログラミングへ
- Java変数の種類:ローカル、インスタンス、クラス変数を徹底解説