2次元配列を宣言するとき
int random[height][width];
そしてそれを関数で使用します
void populate(int random[height][width], int x, int y)
関数の外部で宣言されたエラー可変サイズ型を提供します。私は何か間違ったことをしていること、そしてそれは小さなことだと知っています。私はただ悪い記憶を持っています...
2次元配列を宣言するとき
int random[height][width];
そしてそれを関数で使用します
void populate(int random[height][width], int x, int y)
関数の外部で宣言されたエラー可変サイズ型を提供します。私は何か間違ったことをしていること、そしてそれは小さなことだと知っています。私はただ悪い記憶を持っています...
今すぐステップアップして、多次元配列はCまたはC++で頭を悩ませる価値がないことをお伝えします。1次元配列(または、さらに良いのは標準コンテナー)を使用して、索引付け関数を作成する方がはるかに優れています。
inline int index (int x, int y)
{
return x + y * width;
}
今あなたの問題のために。C ++は、C99可変長配列をサポートしていません。コンパイラは、コンパイル時に配列のサイズを知っている必要があります。たとえば、次の機能は機能しません。
int dim = 4;
int ar[dim];
の場合、コンパイラは幅を正確に指定できるdim
ため(の値は変更されないため)、機能します。これはおそらくあなたが直面している問題です。const
ar
dim
コンパイル時にサイズを変更できるようにする場合は、テンプレート化された参照を作成するなど、より難しいことを行う必要があります。多次元配列はC/C ++での配置方法が原因で、ポインターを使用できません。テンプレート化された例は、次の異常のようになります。
template <int Width, int Height>
void populate(int (&(&random)[Width])[Height], int x, int y);
これは醜いです。
ランタイムの場合は、を使用new
してデータを割り当てるか、コンテナタイプを使用する必要があります。
関数の外部、つまりスタックフレーム内ではなく、一定でない次元(幅、高さ)で配列を定義することはできません。これは、コンパイル時に次元が不明であるためです。定数を使用するか、動的に(ヒープまたはスタックフレームのいずれかで)割り当てます。
配列がパラメーターとして関数に直接渡される(値を渡す)と、配列の最初の要素へのポインターに減衰します。シグニチャで配列の次元を明確に読み取ることができたとしても、それらの次元はコンパイラによって無視されます。その動作はCと互換性があります。
C ++を使用すると、参照によって配列を渡すことができ、それはもう問題にはなりません。
int extract_value( int (&a)[10][10], int row, int col ) {
return a[row][col];
}
int main() {
int a[10][10] = {};
a[5][5] = 1;
std::cout << extract_value( a, 5, 5 ) << std::endl;
int b[5][5];
// extract_value( b, 2, 2 ); // error: the function takes an array of 10x10
}
関数パラメーターは正確に一致する必要があります。つまり、10x10要素の配列のみを取ります。配列サイズで関数をテンプレート化することにより、その制限を取り除くことができます。あなたがそれに着いたら、タイプも:
template <typename T, int Rows, int Cols>
T extract_value( T (&a)[Rows][Cols], int row, int col ) {
return a[row][col];
}
int main() {
int a[5][7] = {};
extract_value( a, 3, 4 );
int b[8][2] = {};
extract_value( b, 7, 1 ); // correct, the compiler matches sizes
double c[4][4] = {};
extract_value( c, 2, 2 ); // different types are allowed
}
このソリューションは、サイズをコンパイル時定数にする必要があり、配列をスタックで割り当てる必要があるという点で、依然として面倒です。これに対する解決策は、バッファ内の動的メモリ(線形)を取得し、前に提案したように、値を取得するためにN座標系から1次元配列に変換するクラスを定義することです。2D行列の実装を提供する演算子のオーバーロードに関するこのFAQで、その方法に関するヒントを得ることができます。それを実装したら、それを関数/メソッドのパラメーターとして使用できます。
私の推奨は、この最後のパスに従うことです。N次元配列を1Dベクトルへの変換を提供するクラスにカプセル化します(C ++ FAQ liteは生のポインターを使用します。私はSTLコンテナーを好みます)。
たとえば、次のように説明します。
//グローバル
const int ARRAY_SIZE = 16
struct ArrayType_t arrayType[ARRAY_SIZE];
ARRAY_SIZEが定数intとして宣言されていても、その値はコンパイル時に初期化されないため、コンパイラは配列のサイズを認識せず、そのようなエラーを出します。ただし、これをハッシュ定義
#define ARRAY_SIZE 16
struct ArrayType_t arrayType[ARRAY_SIZE]
===>として作成すると、ARRAY_SIZEがコンパイル時に定義され、コンパイラがコンパイル時に配列のサイズを認識できるため、これは機能します。
次のようなものを使用できます。
void populate(int height, int width, int **random)
{
//here you can work from random[0][0] to random[height][width]
}
次に、次のように使用できます。
int main()
{
int height=10;
int width=20;
int **myarray = new int*[height];
for( int i=0; i< height; i++ ) myarray[i] = new int[width];
populate( height, width, myarray);
}
ただし、もちろん、バッファオーバーフローに注意する必要があります