NxM 配列にメモリを動的に割り当てる方法はいくつかあります。ここに2つあります:
M 要素の配列へのポインターを宣言してから、そのmalloc
N インスタンスを宣言できます。
double (*podrucje)[11] = malloc(sizeof *podrucje * 123);
C89 の時点では、 の結果をキャストする必要はありmalloc
ません。sizeof
また、オペランド toは式*podrucje
;であることに注意してください。これにより、 と同じ結果が得られsizeof (double) * 11
ます。
podrucje[i][j]
他の 2D 配列と同様に、 この配列にインデックスを付けます。暗黙的にポインターを逆参照します (これは と同等podrucje[i]
であることを思い出してください)。 a[i]
*(a + i)
次のように関数で使用します。
void init(double (*podrucje)[11], size_t rows)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < 11; j++)
podrucje[i][j] = 0.0;
}
これは次のように呼ばれます
init(podrucje, 123);
この方法の欠点は、関数が Nx11 配列でしか操作できないことです。可変長配列をサポートする C99 コンパイラまたは C2011 コンパイラを使用している場合は、ランタイム変数として列数を指定できます。
void foo(void)
{
size_t rows = 123, cols = 11;
double (*podrucje)[cols] = malloc(sizeof *podrucje * rows);
if (podrucje)
init(cols, podrucje, rows);
...
}
// cols must be declared before it can be used
// in an array declarator
//
void init(size_t cols, double(*podrucje)[cols], size_t rows)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
podrucje[i][j] = 0.0;
}
配列の操作が完了したら、次のように割り当てを解除します。
free(podrucje);
もう 1 つの方法は、次のように各行を個別に割り当てることです。
size_t rows = 123, cols = 11;
double **podrucje = malloc(sizeof *podrucje * rows);
if (!podrucje)
{
// malloc failed; handle allocation error here
}
else
{
size_t i;
for (i = 0; i < rows; i++)
{
podrucje[i] = malloc(sizeof *podrucje[i] * cols);
if (!podrucje[i])
{
// malloc failed; handle allocation error here
}
}
}
そして、次のように関数で使用します。
void foo()
{
double **podrucje;
// allocate array as above
init(foo, rows, cols);
...
}
void init(double **podrucje, size_t rows, size_t cols)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
podrucje[i][j] = 0.0;
}
配列の使用が終了したら、次のように割り当てを解除します。
for(i = 0; i < rows; i++)
free(podrucje[i]);
free(podrucje);
最初の方法では、メモリを単一の連続したブロックとして割り当てます。2 つ目は、それを一連のより小さな不連続なチャンクに割り当てます。配列が特に大きいか、ヒープが特に断片化されている場合、最初の方法は失敗し、2 番目の方法は成功する可能性があります。可変長配列をサポートしていないコンパイラを使用している場合、コンパイル時に列数を指定する必要があるため、最初の方法は柔軟性に欠けます。
同じ索引付け方法が両方の形式でどのように機能するのでしょうか?
最初のケースでは、それぞれpodrucje[i]
が の 11 要素の配列ですdouble
。j
他の配列と同様に機能します。2 番目のケースでは、それぞれpodrucje[i]
が double へのポインターです。a[i]
は として評価されるため、*(a + i)
配列のインデックス付けは配列式と同様にポインター式でも機能します。