コンパイラエラー

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キーワードの不適切な使用がエラーの根本原因であり、そのエラーメッセージの解析方法および、関数宣言との違いが理解できる内容となっています。

また、適切なストレージクラスの利用方法や、外部変数とローカル変数の正しい宣言方法についても具体的なコード例とともに説明しています。

関連記事

Back to top button