18

関数内の 2 次元配列に動的メモリを割り当てる方法は? 私はこの方法を試しました:

int main()
{
  int m=4,n=3;
  int** arr;
  allocate_mem(&arr,n,m);
}


void allocate_mem(int*** arr,int n, int m)
{
  *arr=(int**)malloc(n*sizeof(int*));
  for(int i=0;i<n;i++)
    *arr[i]=(int*)malloc(m*sizeof(int));
} 

しかし、うまくいきません。

4

8 に答える 8

33

演算子の優先順位が差分演算子よりも高い*arr[i]=(int*)malloc(m*sizeof(int));ため、コードが間違っています。式では、最初に評価されてから適用されます。必要なのはその逆です(逆参照してから適用します)。[]**arr[i]arr[i]*arr[]

(*arr)[i]演算子の優先順位を上書きするには、次のような括弧を使用します。これで、コードは次のようになります。

void allocate_mem(int*** arr, int n, int m)
{
  *arr = (int**)malloc(n*sizeof(int*));
  for(int i=0; i<n; i++)
    (*arr)[i] = (int*)malloc(m*sizeof(int));
} 

上記のコードで何が起こるかをさらに理解するには、この回答を読んでください。

作業が終了したら、動的に割り当てられたメモリの割り当てを常に明示的に解除することが重要です。上記の関数によって割り当てられたメモリを解放するには、次のようにする必要があります。

void deallocate_mem(int*** arr, int n){
    for (int i = 0; i < n; i++)
        free((*arr)[i]);
    free(*arr); 
}

さらに、2D配列を作成するためのより良い方法は、以下のように1回の関数呼び出しで連続したメモリを割り当てることです。malloc()

int* allocate_mem(int*** arr, int n, int m)
{
  *arr = (int**)malloc(n * sizeof(int*));
  int *arr_data = malloc( n * m * sizeof(int));
  for(int i=0; i<n; i++)
     (*arr)[i] = arr_data + i * m ;
  return arr_data; //free point
} 

このメモリの割り当てを解除するには:

void deallocate_mem(int*** arr, int* arr_data){
    free(arr_data);
    free(*arr);
}

2番目の手法では、mallocは2回しか呼び出されないため、割り当て解除コードでは、freeはループで呼び出すのではなく、2回だけ呼び出されることに注意してください。したがって、この手法の方が優れているはずです。

于 2013-02-25T08:21:56.107 に答える
3

配列のサイズを変更する必要がない場合 (可能ですが、少し複雑になります)、C で 2D 配列を作成する簡単で効率的な方法があります。

http://c-faq.com/aryptr/dynmuldimary.htmlをご覧ください。

2 番目の方法 (array2 という配列の場合) は非常に単純で、負担が少なく (malloc の戻り値のテストを追加してみてください)、はるかに効率的です。

200x100 の配列で、100000 回の割り当てと割り当て解除を行ったところ、ベンチマークを実行しました。

  • 方法 1 : 1.8 秒
  • 方法 2 : 47ms

また、配列内のデータはより連続的になり、速度が向上する可能性があります(コピー、リセットするためのより効率的な手法が得られる可能性があります...この方法で割り当てられた配列)。

于 2013-02-25T12:36:09.963 に答える
1

これは、配列にスペースを割り当てるための不必要に複雑な方法です。このイディオムを考えてみましょう:

int main(void) {
    size_t m = 4, n = 3;
    int (*array)[m];
    array = malloc(n * sizeof *array);
    free(array);
}
于 2013-02-25T09:22:52.757 に答える
0

2次元配列にメモリを割り当てるために、次のコードを試しました。

    #include<stdio.h>
    #include<malloc.h>
    void main(void)
    {
    int **p;//double pointer holding a 2d array
    int i,j;
    for(i=0;i<3;i++)
    {
    p=(int**)(malloc(sizeof(int*)));//memory allocation for double pointer
    for(j=(3*i+1);j<(3*i+4);j++)
    {
    *p = (int*)(malloc(sizeof(int)));//memory allocation for pointer holding integer array
    **p = j;                  
    printf(" %d",**p);//print integers in a row 
    printf("\n");
    p++;
    }
    }
    }

上記のコードの出力は次のとおりです。

1 2 3

4 5 6

7 8 9

ポインタの観点から 2 次元配列を理解するには、それがメモリにどのように割り当てられるかを理解する必要があります。次のようになります。

                1    2    3
    1000 -->   100  104  108

                4    5    6
    1004 -->   200  204  208

                7    8    9
    1008 -->   300  304  308 

上記から、double ポインターであるポインター p にメモリを割り当てると、整数の配列を指していることがわかります。したがって、この例では、0x1000 がポインター p であることがわかります。

このポインターは、整数の配列である整数ポインター *p を指しています。メモリが内側の for ループ内に割り当てられている場合、最初の反復中にポインターは 0x100 であり、**p = j を割り当てると、整数値 1 を指します。同様に、ループの次の繰り返しで 2 と 3 を指します。

外側のループの次の反復の前に、次の反復内で double ポインターがインクリメントされます。ループの次の反復のために。

于 2014-03-26T16:57:31.747 に答える
-1

次のコードを試してください。

 void allocate_mem(int*** arr,int n, int m)
{
  *arr=(int**)malloc(n*sizeof(int*));
  for(int i=0;i<n;i++)
    *(arr+i)=(int*)malloc(m*sizeof(int));
} 
于 2016-08-24T11:20:16.793 に答える
-1

2d 配列は、malloc を使用して動的に配列します。

int row = 4;
int column = 4;
int val = 2;
// memory allocation using malloc   

int **arrM = (int**)malloc (row*sizeof(int*));

for (int i=0;i<row;i++)
{
    arrM[i] = (int*)malloc(column*sizeof(int));
    // insert the value for each field
    for (int j =0;j<column;j++,val++)
    {
      arrM[i][j]     = val;
    }
}

// De-allocation

for (int i=0;i<row;i++)
{
    free(arrM[i]);
}
free(arrM);
arrM = 0;

//
// Now using New operator:
//

int **arr = new int*[row];
int k = 1;
for (int i=0;i<row;i++)
{
    arr[i] = new int[column];
    // insert the value for each field
    for (int j =0;j<column;j++,k++)
    {
      arr[i][j]  = k;
    }
}
cout<<"array value is = "<<*(*(arr+0)+0)<<endl;
cout<<"array value is = "<<*(*(arr+3)+2)<<endl;

// Need to deallcate memory;

for (int i=0;i<row;i++)
{
delete [] arr[i];
}
delete []arr;
arr = 0;
于 2017-01-10T16:34:46.913 に答える