1

2次元配列を宣言するとき

int random[height][width];

そしてそれを関数で使用します

void populate(int random[height][width], int x, int y)

関数の外部で宣言されたエラー可変サイズ型を提供します。私は何か間違ったことをしていること、そしてそれは小さなことだと知っています。私はただ悪い記憶を持っています...

4

5 に答える 5

4

今すぐステップアップして、多次元配列はCまたはC++で頭を悩ませる価値がないことをお伝えします。1次元配列(または、さらに良いのは標準コンテナー)を使用して、索引付け関数を作成する方がはるかに優れています。

inline int index (int x, int y)
{
  return x + y * width;
}

今あなたの問題のために。C ++は、C99可変長配列をサポートしていません。コンパイラは、コンパイル時に配列のサイズを知っている必要があります。たとえば、次の機能は機能しません。

int dim = 4;
int ar[dim];

の場合、コンパイラは幅を正確に指定できるdimため(の値は変更されないため)、機能します。これはおそらくあなたが直面している問題です。constardim

コンパイル時にサイズを変更できるようにする場合は、テンプレート化された参照を作成するなど、より難しいことを行う必要があります。多次元配列はC/C ++での配置方法が原因で、ポインターを使用できません。テンプレート化された例は、次の異常のようになります。

template <int Width, int Height>
void populate(int (&(&random)[Width])[Height], int x, int y);

これは醜いです。

ランタイムの場合は、を使用newしてデータを割り当てるか、コンテナタイプを使用する必要があります。

于 2009-09-16T19:42:18.973 に答える
1

関数の外部、つまりスタックフレーム内ではなく、一定でない次元(幅、高さ)で配列を定義することはできません。これは、コンパイル時に次元が不明であるためです。定数を使用するか、動的に(ヒープまたはスタックフレームのいずれかで)割り当てます。

于 2009-09-16T19:35:21.017 に答える
1

配列がパラメーターとして関数に直接渡される(値を渡す)と、配列の最初の要素へのポインターに減衰します。シグニチャで配列の次元を明確に読み取ることができたとしても、それらの次元はコンパイラによって無視されます。その動作は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コンテナーを好みます)。

于 2009-09-16T21:40:15.803 に答える
1

たとえば、次のように説明します。

//グローバル

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がコンパイル時に定義され、コンパイラがコンパイル時に配列のサイズを認識できるため、これは機能します。

于 2011-11-24T05:47:18.373 に答える
-1

次のようなものを使用できます。

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);
}

ただし、もちろん、バッファオーバーフローに注意する必要があります

于 2009-09-16T20:22:58.157 に答える