C言語 コンパイラエラー C2205 の原因と対処法について解説
関数内などのブロックスコープで、例えばextern
で宣言された変数に初期化子を付けると、このエラーが発生します。
外部変数はグローバルスコープで定義し初期化する必要があるため、コードの記述を見直して修正してください。
エラーC2205の現象と特徴
エラーC2205は、外部変数を関数内などのブロックスコープで初期化しようとした場合に発生するエラーです。
このエラーが発生すると、コンパイラは次のようなメッセージを出力します。
'identifier': 外部変数は、ブロック スコープでは初期化できません
これは、外部変数の初期化がグローバルスコープでのみ許可されているためです。
エラーメッセージの内容と確認方法
エラーメッセージには、対象となる変数の識別子および「外部変数は、ブロック スコープでは初期化できません」と記載されます。
エラーが発生した場合は、以下の点を確認してください。
- 変数が
extern
キーワードで宣言されているか - 変数の初期化が関数などのブロックスコープ内で行われていないか
エラーメッセージを確認することで、初期化場所の誤りに気付くことができ、該当箇所を修正する手がかりとなります。
発生箇所の具体例
以下の例では、関数内でextern
変数を初期化しているため、エラーC2205が発生します。
#include <stdio.h>
// 外部での定義が期待される変数を関数内で初期化してしまう例
void sampleFunction(void) {
extern int globalValue = 10; // ここで初期化してしまうとエラーC2205が発生する
printf("globalValue = %d\n", globalValue);
}
int main(void) {
sampleFunction();
return 0;
}
// コンパイル時に以下のようなエラーメッセージが出力される例
'globalValue': 外部変数は、ブロック スコープでは初期化できません
外部変数の仕様と取り扱い
外部変数は、プログラム全体で共有される変数として定義され、グローバルスコープでのみ初期化が可能です。
そのため、正しく定義と初期化を行うことが重要です。
extern変数の定義と初期化のルール
extern
キーワードは、変数が他のファイルもしくはグローバルスコープで定義されていることを示すために用いられます。
以下のポイントに注意してください。
extern
宣言そのものは初期化を行ってはいけません- 初期化は変数がグローバルスコープで定義される際にのみ行う
- 複数のファイルでその変数を利用する場合、1箇所で定義して他の箇所では
extern
宣言を行う
たとえば、正しい定義方法は以下のようになります。
// global_definitions.c
#include <stdio.h>
int globalValue = 10; // グローバルスコープで初期化
// 他のファイルで外部変数を利用する場合は、以下のように宣言するだけ
// extern int globalValue;
ブロックスコープとグローバルスコープの違い
ブロックスコープは、関数内や制御構文内で有効な変数のスコープです。
グローバルスコープは、ソースファイル全体で有効な変数のスコープとなります。
以下の点が主な違いです。
- グローバル変数はプログラム全体で共有可能
- ブロック変数は宣言されたブロック内でのみ有効
- 外部変数の初期化はグローバルスコープでのみ許可される
実際のコード例では、グローバル変数とローカル変数の宣言位置によってアクセス可能範囲が異なることが確認できます。
#include <stdio.h>
int globalVar = 5; // グローバル変数(グローバルスコープ)
void checkScope(void) {
int localVar = 3; // ローカル変数(ブロックスコープ)
printf("globalVar = %d, localVar = %d\n", globalVar, localVar);
}
int main(void) {
checkScope();
return 0;
}
globalVar = 5, localVar = 3
原因の解析
エラーC2205は、外部変数の初期化位置を誤ることが原因です。
ここでは、具体的な初期化方法の誤りとその結果生じるエラーの発生メカニズムについて説明します。
誤った初期化方法の例示
外部変数をextern
で宣言しながら、間違った場所で初期化を試みることが原因です。
以下に誤った初期化方法の例を示します。
関数内でのextern変数初期化失敗例
先ほどの例のように、関数内でextern
変数を初期化することはできません。
これは、extern
宣言は単に変数の存在を示しているだけであり、実体を持たせる定義としては認識されないためです。
#include <stdio.h>
void wrongInit(void) {
extern int sharedValue = 20; // 関数内で初期化するとエラーC2205が発生する
printf("sharedValue = %d\n", sharedValue);
}
int main(void) {
wrongInit();
return 0;
}
// コンパイル時にエラーが発生します。
// 'sharedValue': 外部変数は、ブロックスコープでは初期化できません
記述ミスによるエラー発生の仕組み
外部変数の定義と宣言場所に誤りがあると、コンパイラは以下のように判断します。
- 関数内での初期化はローカル変数とみなされるが、
extern
指定があるため矛盾が発生する - 変数の複数回定義が発生する可能性があるため、明確にグローバルスコープでの定義が求められる
これにより、エラーメッセージが出力され、プログラムのコンパイルが中断される仕組みとなっています。
対処方法の検討
正しい対処としては、外部変数の定義と初期化をグローバルスコープに移動させ、関数内での初期化を行わないことが挙げられます。
これにより、エラーC2205を回避し、プログラム全体で変数の一貫性が保たれるようになります。
正しい外部変数の定義と初期化手順
正しく外部変数を扱う手順は以下の通りです。
- グローバルスコープに変数の定義と初期化を記述する
- 他のファイルや関数内では、
extern
宣言を用いて変数の存在を参照するのみ
グローバルスコープでの定義方法
グローバルスコープで正しく定義するためには、変数を関数の外側で宣言し、値を初期化します。
以下のコードは、正しい定義の例となります。
#include <stdio.h>
int sharedValue = 20; // グローバルスコープでの定義と初期化
void printSharedValue(void) {
// 関数内で初期化を行わず、グローバル変数を参照するのみ
printf("sharedValue = %d\n", sharedValue);
}
int main(void) {
printSharedValue();
return 0;
}
sharedValue = 20
修正コードの具体例
誤ったコード例を修正した具体例をご紹介します。
以下のコードは、関数内での初期化をグローバルスコープでの定義に変更したものです。
#include <stdio.h>
// 外部変数の正しい定義(グローバルスコープ)
int globalData = 100;
// 他のファイルから参照する場合は、ヘッダファイルなどで以下の宣言を行う
// extern int globalData;
void displayGlobalData(void) {
// 関数内では、グローバル変数を参照するのみ
printf("globalData = %d\n", globalData);
}
int main(void) {
displayGlobalData();
return 0;
}
globalData = 100
まとめ
本記事では、C言語のエラーC2205について、外部変数をブロックスコープで初期化できない原因と、そのエラーメッセージの内容、確認方法を解説しました。
さらに、extern変数の定義や初期化のルール、グローバルスコープとブロックスコープの違いを具体例を交えて説明し、正しい外部変数の取り扱い方法や修正コードを紹介しています。