C言語のC2090エラーについて解説 配列返却が原因のポインター返却への適切な対策方法
関数が配列をそのまま返す記述はできず、配列へのポインターを返す必要があります。
直接配列を返そうとすると、C2090 エラーが発生します。
このエラーを解消するためには、関数の戻り値として配列ではなく、その先頭要素を指すポインターを指定する方法が一般的です。
関数の返却仕様と配列の取り扱い
配列とポインターの基本的な違い
配列は固定サイズのメモリ領域を扱うため、宣言時にサイズを指定する必要があります。
これに対して、ポインターはメモリ上のアドレスを管理するため、配列と同様の使い勝手が得られる場合があります。
以下のポイントに注意してください。
- 配列は宣言後にサイズが固定され、関数に渡す際もサイズ情報を別途伝える必要があります
- ポインターは関数間で柔軟にアドレスをやり取りできるため、返却値として利用する際に便利です
- 配列そのものは返却することができませんが、配列の先頭アドレスを指すポインターを返却することは可能です
C言語の関数戻り値仕様
C言語では、関数の戻り値として配列そのものを返すことが認められていません。
関数が返せる型は、基本型や構造体、ポインターなどに限定されています。
そのため、配列の先頭要素へのポインターを返却する方法を採用するケースが多いです。
配列返却ができない理由
関数が実行されるとローカル変数の配列はスタック領域に確保され、関数終了時に破棄されます。
配列そのものを返すと、呼び出し元で不正なメモリアクセスが起きる可能性があるため、C言語では配列を直接返却することが許されません。
また、配列のサイズ情報が利用できなくなる点も注意が必要です。
C2090エラーの原因と具体例
エラー発生の背景
配列を返す関数を定義しようとすると、C2090エラーのようなコンパイルエラーが発生します。
これは、関数戻り値として配列型が認められていないためです。
直接配列を返そうとする試みは、コンパイラによって拒否されます。
誤った関数定義の例
間違った関数定義の場合、関数の戻り値に配列型を指定することになります。
例えば以下のようなコードはコンパイル時にエラーが発生します。
直接配列返却によるエラーケース
以下は誤った定義のサンプルコードです。
#include <stdio.h>
// 誤った関数定義:配列をそのまま返そうとするとエラーになります
int func1(void)[]
{
// 配列の定義と返却を試みますが、この書き方はエラーになります
}
int main(void)
{
// 呼び出し例
int *result = func1();
return 0;
}
上記のコードは、配列を直接返そうとするため、コンパイラからエラーが出る可能性が高いです。
エラー解消のための対策
戻り値をポインターに変更する方法
配列そのものを返却する代わりに、配列の先頭アドレスを指すポインターを返却する方法に変更します。
これにより、呼び出し元で正しく配列にアクセスすることが可能になります。
注意点として、返却されたポインターが指すメモリの管理に気を付ける必要があります。
修正例の説明とコード例
下記は正しい実装例です。
関数は引数として渡された配列の先頭アドレスをそのまま返却する形になります。
#include <stdio.h>
// 正しい関数定義:配列の先頭アドレスを返却します
int* getArray(int *array)
{
// そのまま配列の先頭アドレスを返します
return array;
}
int main(void)
{
// ローカル配列の定義
int sample[5] = {1, 2, 3, 4, 5};
// getArray関数で配列の先頭アドレスを取得
int *pArray = getArray(sample);
// 取得した配列の値を順に表示
for (int i = 0; i < 5; i++)
{
printf("%d ", pArray[i]);
}
printf("\n");
return 0;
}
1 2 3 4 5
このコードでは、getArray
関数によってローカル配列の先頭アドレスが返され、呼び出し元で配列の各値を表示しています。
実際のコードで使用する際は、返却ポインターが有効なメモリ領域を指しているかを十分に確認してください。
エラー回避時の注意事項
関数定義時に気を付ける点
関数定義の際には、戻り値の型と返却内容が適切に一致しているかを意識してください。
配列を返却する場合、必ずその先頭アドレスを持つポインター型に変更する必要があります。
以下の点に注意してください。
- 関数の戻り値として配列型ではなくポインター型を使用する
- ローカル配列を返却する場合、スコープ外でのメモリアクセスに注意する
よくある記述ミスの回避方法
よくあるミスとして、関数宣言と定義の型指定が一致しなかったり、返却したポインターが無効なメモリを指すことがあります。
以下のリストを参考に修正を行ってください。
- 関数の戻り値と返却値の型を正しく合わせる
- ローカル配列のポインターを返却する場合、スタックの寿命に注意する
- グローバル変数やヒープ領域を利用する場合は、適切な初期化と解放を行う
まとめ
今回の内容を活かし、配列返却の代わりにポインター返却を使った設計を意識していただければ嬉しいです。
適切な型を選択することが、コンパイルエラーや実行時の不具合回避につながります。