1

次のコードを使用して、C で動的な 2 次元配列を割り当てようとしています。

int **allocateMatrix(int rows, int columns) {

    int i = 0;
    int **p = NULL;

    p = (int**) calloc(rows, sizeof(int*));
    for(; i < rows; i++) {

        p[i] = (int*) calloc(columns, sizeof(int));
    }

    return p;
}

コードは機能しますが、実際には必要なメモリの 2 倍を割り当てています。

たとえば、引数rows = 2を渡すと、 columns = 32 行 x 8 列の配列が得られます。

私は何か間違ったことをしていますか?

ありがとうございました。

編集

(ファイルから読み込まれる) マトリックスの内容は次のとおりです。

-1 5 0
4 0 2

これは、値の割り当てと代入後のメモリの外観です。

メモリー

4

4 に答える 4

1

AFAICT、20個の要素を持つ配列のスクリーンショットは.. Netbeansに(それを使用して@20)メモリ位置( **(matrix))から始まる20個の要素を表示するように指示したためです。「@3」に変更するとどうなりますか?

ただし、このコメントに基づいて:

実際は倍以上です。値を割り当てようとすると、それらはメモリ内で連続していませんが、シフトされているためです(netbeansのデバッグウィンドウのウォッチから確認できます)。

メモリを割り当てるときは、オペレーティング システムからどの領域を使用できるかを要求する方法と、オペレーティング システムによって割り当てられた領域のうち、まだ使用されていない領域を把握するライブラリを呼び出します。

アロケーターがどのように機能するかについて、正しい場合とそうでない場合があると仮定しています。特に仮想ページング メカニズムが原因で、予期しない方法でスペースを効率的に割り当てることができます。つまり、アロケータへの連続した呼び出しは、連続したメモリを割り当てることが保証されておらず、めったに割り当てられません。

double 配列スタイルの構造にポインターの配列を使用したい場合、およびより「期待される」方法で連続したアドレスが絶対に必要な場合は、これを試すことができます。

int **allocateMatrix(int rows, int columns) {

    int i = 0;
    int **p = NULL;
    int *d = NULL;


    p = (int**) calloc(rows, sizeof(int*));
    d = (int*) calloc(rows * columns, sizeof(int));

    for(; i < rows; i++) {
        p[i] = d + i * columns;
    }

    return p;
}

(コードはテストされていません)

于 2013-11-14T22:26:07.300 に答える
0

次のアプローチを使用できます (データを格納するために余分なメモリは必要ありません。実際にはメモリ内の 1D 連続配列です)。

#include <stdlib.h>
#include <stdio.h>

int (*allocateMatrix(int rows, int columns))[]{
    int (*p)[columns] = calloc(rows, columns * sizeof(int)),
        i, j;
    for (i = 0; i < rows; i++) {
      for (j = 0; j < columns; j++) {
        p[i][j] = rows*i + j;
      }
    }
    return p;
}


int main(int argc, char *argv[]) {
  int rows = 4, cols = 5,
     (*array)[cols] = allocateMatrix(rows,cols);

  int i, j;
  for (i = 0; i < rows; i++) {
    for (j = 0; j < cols; j++) {
      printf("array[%d][%d] = %2d\n", i, j, array[i][j]);
    }
  }
  free(array);
  return 0;
}

出力:

array[0][0] =  0
array[0][1] =  1
array[0][2] =  2
array[0][3] =  3
array[0][4] =  4
array[1][0] =  4
array[1][1] =  5
array[1][2] =  6
array[1][3] =  7
array[1][4] =  8
array[2][0] =  8
array[2][1] =  9
array[2][2] = 10
array[2][3] = 11
array[2][4] = 12
array[3][0] = 12
array[3][1] = 13
array[3][2] = 14
array[3][3] = 15
array[3][4] = 16
于 2013-11-14T22:52:13.213 に答える
0

これは、ポインターを格納するための二次元配列サイズ (rows*columns*sizeof(int*)) と、実際の値 (rows*columns*sizeof(int)) を格納するための二次元配列スペースがあるためではありませんか?

于 2013-11-14T22:29:34.420 に答える