C言語のコンパイラエラー C2390 の原因と対策を解説
この記事では、C言語で発生するコンパイラエラー C2390 について簡潔に説明します。
エラー C2390 は、ストレージクラス指定が不適切な場合に表示されるもので、たとえばグローバル変数に対して register キーワードを使用すると発生します。
関数やローカル変数では適切なストレージ指定が行えるため、その点に注意するとエラー解消のヒントになります。
エラー C2390 発生の背景
C2390 エラーは、ストレージクラスの指定が不適切な場合に発生するエラーです。
特に、グローバル変数に対して register
キーワードを用いると、コンパイラがエラーを出力して警告するケースが多く見受けられます。
C言語の仕様では、グローバル領域の変数には自動ストレージが適用されるため、明示的に register
を指定する必要はなく、むしろ禁止されています。
エラーメッセージの解析
エラーメッセージには
「identifier
: ストレージクラス specifier
が正しくありません」
と記述されており、これにより該当の識別子に対して指定されたストレージクラスが許容されていないことが明示されています。
このエラーは、主に以下の2点に注目することで解析できます。
- 該当の識別子がどのスコープに属しているか
- 指定されたストレージクラスがそのスコープで有効かどうか
発生対象と使用状況
エラー C2390 は主に以下のような状況で発生します。
- グローバル変数に対して
register
を指定している場合 - 意図せずにグローバルスコープで変数を定義している場合
一方、関数内(ローカルスコープ)で使用する変数の場合は、register
キーワードの指定が許容される例もあります。
ただし、現在のコンパイラ最適化では、このキーワードの利用効果は限定的であり、デフォルトの自動変数として扱われることが一般的です。
エラー C2390 の原因
エラー C2390 の根本的な原因は、不適切なストレージクラス指定にあります。
特に、グローバル変数に対して register
キーワードを使用することが、C言語の仕様に反するためエラーとなります。
グローバル変数での register 使用の問題
グローバルスコープにおいては、変数は自動的にストレージが割り当てられるため、register
のような一時的な最適化指示は不要です。
C言語の標準では、グローバル変数に対するストレージクラス指定は許容されず、register
を指定するとエラー C2390 が発生します。
関数宣言との違い
関数宣言や関数内での局所変数の場合、register
キーワードの指定が可能であっても、現代のコンパイラ最適化では自動ストレージによる最適化と大きな差は生じません。
そのため、グローバル変数に対して一貫して使用することは推奨されません。
また、関数の仮引数として register
を用いることで、メモリ上ではなくレジスタ上での利用を促す意図がありますが、実際の最適化はコンパイラ任せとなります。
ローカル変数における正しいストレージクラス指定
ローカル変数に関しては、何も指定しなければ自動的に自動ストレージクラスが適用されます。
そのため、特別な理由がない限り、register
キーワードを明示する必要はありません。
さらに、現代のコンパイラは自動的に最適な最適化を行うため、明示的な register
指示は必ずしも有利とは限りません。
C2390 の対策
エラー C2390 を解消するためには、ストレージクラス指定を正しく調整する必要があります。
特に、グローバル変数の場合は、register
キーワードを削除し、仮パラメーターおよびローカル変数は自動ストレージを利用するようにします。
register キーワードの適切な使用制限
register
キーワードは、古い最適化指示として一部で利用される場合がありますが、グローバル変数に対して使用するとエラーとなります。
そのため、使用場所を限定し、以下の点に注意する必要があります。
外部変数の場合の宣言方法
外部変数を宣言する際には、明示的なストレージクラス指定を省略し、デフォルトの自動ストレージクラスに任せます。
もし他ファイル間で共有する必要がある場合は、変数を extern
宣言することで適切なリンクが行われます。
仮パラメーター・ローカル変数の自動ストレージ利用
関数の仮引数やローカル変数に対しては、意図しない場合を除いて register
を指定せずに、自動ストレージクラスに委ねるのが安全です。
これにより、コードの可読性が向上し、コンパイラが最適な配置を自動的に行うため、パフォーマンスの低下を防ぐことができます。
コード例による対処方法
エラー発生前と解消後のコード例を示します。
これらの例により、正しいストレージクラスの指定方法が実際のコード内でどのように適用されるかを確認できます。
エラー発生前のコードパターン
以下のコードは、グローバル変数に register
キーワードを指定しているため、エラー C2390 が発生する例です。
#include <stdio.h>
// グローバル変数に register を指定するとエラーとなる
register int globalCounter; // エラー C2390 が発生する
int main(void) {
// ローカル変数で register を使用する場合はOK
register int localCounter = 0;
printf("Local Counter: %d\n", localCounter);
return 0;
}
(コンパイル時にエラー C2390 が表示される)
エラー解消後のコード例と解説
以下のコード例では、グローバル変数から register
キーワードを削除し、正しい形で宣言しています。
#include <stdio.h>
// グローバル変数は自動ストレージクラスとなるため、register を指定しない
int globalCounter;
int main(void) {
// ローカル変数の場合、必要なければ register は指定しない
int localCounter = 0;
// グローバル変数の値を利用する例
globalCounter = 5;
printf("Global Counter: %d\n", globalCounter);
printf("Local Counter: %d\n", localCounter);
return 0;
}
Global Counter: 5
Local Counter: 0
まとめ
本記事では、C2390エラーの発生背景、原因、対策について解説しています。
グローバル変数におけるregister
キーワードの不適切な使用がエラーの根本原因であり、そのエラーメッセージの解析方法および、関数宣言との違いが理解できる内容となっています。
また、適切なストレージクラスの利用方法や、外部変数とローカル変数の正しい宣言方法についても具体的なコード例とともに説明しています。