変数の宣言と初期化は、非常に厳格で時には明白でないルールを持つC言語の基礎です。変数をどのように、そしてどこで宣言したかによって、初期値(初期化に関して)、およびメモリオブジェクトとの関係(宣言と定義に関して)が決まります。
C言語は、メモリの最適化が優先されていた時代に遡ります。開発者は変数を自ら宣言し初期化しなければならず、そうしなければプログラムの動作は予測不可能なものになりました。現代のCコンパイラでは、わずかな逸脱でもリンクエラーや不明な初期化による「ゴミ」が生成されることがあります。
主なエラー:
コード例:
#include <stdio.h> int global_var; // 定義、自動初期化 = 0 static int static_global_var; // staticファイル、自動初期化 = 0 extern int extern_var; // 宣言、他の場所で定義されている void foo() { int local_var; // 自動的、初期化されていない -> ゴミ static int static_local_var; // static、自動初期化 = 0 }
重要な特徴:
1. 自動変数(staticやexternなしのローカル)はコンパイラによって自動的に0に初期化されますか?
いいえ、ゴミを含んでいます。初期化前に使用するのはエラーです。
2. 異なるファイルでexternを使って変数を何度も定義できますか?
いいえ、一つの定義が必要で、残りはexternによる宣言のみ、さもなければリンクエラーが発生します。"multiple definition"や"undefined symbol"のエラーが出ます。
3. 関数の宣言と定義の違いは何ですか?
宣言はプロトタイプのみ(本体なし); 定義には必ず関数本体が含まれます。変数の場合、externによる宣言はメモリを予約しませんが、関数の場合は両方の形が許可されます。
グローバル変数int counter;が二つのヘッダーファイルで宣言されています。プロジェクトはリンクエラーmultiple definitionで失敗しました。
利点:
欠点:
ヘッダーはextern int counter;を記載し、定義はint counter = 0; — これは一つのCファイルにのみ存在します。
利点:
欠点: