C言語で書いたソースコードをコンパイルするとC2371「再定義されています。異なる基本型です」のエラーでコンパイルできないことがあります。
この記事では
- なぜC2371エラーが発生するのか、
- C2371エラーを解消する方法
の2つを解説していきます。
C2371エラーが発生する原因
C2371エラーのメッセージは「再定義されています。異なる基本型です」ですが、そのメッセージ通り、同じ同じ名前の変数名が同じ関数内などで宣言されてしまっている状態です。
問題なのは変数名なので型は関係ありません。ですので以下のコードはC2371エラーが発生します。
#include<stdio.h>
int main() {
int a = 0;
char a = 0; //C2371
a = 30;
return 0;
}
コードC2371は警告ではなくエラーとして処理されるため、コンパイルできません。
C2371エラーを解消する方法
同じ関数内で同じ名前の変数を宣言しない
一番確実な解決方法です。同じ変数名の編集をかけなければいけない事情がある場合は、少し変数名を長めにして区別しやすいようにするのがおすすめです。
#include<stdio.h>
int main() {
int old_count = 0;
int new_count = 10;
return 0;
}
str1・str2のように連番にするのは非推奨です。
変数名を分けるという目的を果たすことはできますが、どの変数を何に使ってるのか分からなくなってしまうので可読性が低下します。
変数宣言行にコメントを残せばいいと思うかもしれませんが、プログラムをトレースするときが大変なので、できるだけ意味のある変数名をつけるようにしてください。
スコープを分ける
C言語・C++は、スコープの概念があります。言葉で説明するよりもプログラムで見たほうが早いでしょう。
#include<stdio.h>
int main() {
int a = 10;
{
int a = 20;
//20が出力される
printf("%d",a);
}
//10が出力される
printf("%d", a);
return 0;
}
こちらのコードはどちらも同じ名前の変数名が使われていますが、実体は全く別の変数となっています。
スコープとは変数を利用できる有効範囲のことで{}内で宣言された変数や定数はその{}内でしか使うことができません。例えば以下のコードはエラーになります。
#include<stdio.h>
int main() {
int a = 10;
{
int b = 20;
//変数aは同じmain関数のスコープ内なのでエラーに鳴らない
printf("%d",a);
//同じスコープなのでエラーにならない
printf("%d",b);
}
//変数aは同じスコープなので問題なし
printf("%d", a);
//変数bはスコープ外なのでエラーが発生
printf("%d", b);
return 0;
}
{}はfor文やif文で使うことが多いですが、{}だけでもスコープ範囲を定める目的で使用できます。
Visual StudioのIntelliSense(オートコンプリート機能)は使用できる変数や定数名のみを認識します。変数や定数が多くなる場合はスコープで変数の有効範囲を狭めることでIntelliSenseの補完候補を減らすテクニックがあります。
スコープを明示的に示すことで、変数を使っている範囲がわかりやすくなって可読性があがります。初心者には難しいかもしれませんが、きれいで読みやすいプログラムを書く際には役立つテクニックの一つです。
変数・定数管理ができていない可能性が高い
本来は同じクラスや関数内で同じ変数名や定数名を使うべきではありません。書いた本人は理解していたとしても後でソースコードを確認した時の可読性が低下します。
- 同じクラスや関数内では同じ名前の変数が使われない前提でトレースする関係でバグを見落とす可能性がある(for文内でしか使われないループ変数(i,j,kなど)は除く)
- バグが発生したときにスコープの検証などが面倒
ループ変数で使われるi,j,kなど繰り返し使用することが一般的になっている変数名は大丈夫ですが、「cnt・str・text」などありきたりな変数名や定数名を使用する際は注意してください。