How to dynamically allocate a contiguous block of memory for a 2D array

后端 未结 7 1269
傲寒
傲寒 2020-12-05 05:10

If I allocate a 2D array like this int a[N][N]; it will allocate a contiguous block of memory.

But if I try to do it dynamically like this :

<
相关标签:
7条回答
  • 2020-12-05 05:42

    You can treat dynamically allocated memory as an array of a any dimension by accessing it in strides:

    int * a = malloc(sizeof(int) * N1 * N2 * N3);  // think "int[N1][N2][N3]"
    
    a[i * N2 * N3 + j * N3 + k] = 10;              // like "a[i, j, k]"
    
    0 讨论(0)
  • 2020-12-05 05:44

    The best way is to allocate a pointer to an array,

    int (*a)[cols] = malloc(rows * sizeof *a);
    if (a == NULL) {
        // alloc failure, handle or exit
    }
    
    for(int i = 0; i < rows; ++i) {
        for(int j = 0; j < cols; ++j) {
            a[i][j] = i+j;
        }
    }
    

    If the compiler doesn't support variable length arrays, that only works if cols is a constant expression (but then you should upgrade your compiler anyway).

    0 讨论(0)
  • 2020-12-05 05:51

    You can typedef your array (for less headake) and then do something like that:

    #include <stdlib.h>
    #define N 10
    typedef int A[N][N];
    int main () {
      A a; // on the stack
      a[0][0]=1;
      A *b=(A*)malloc (sizeof(A)); // on the heap
      (*b)[0][0]=1;
    }
    
    0 讨论(0)
  • 2020-12-05 05:57

    Excuse my lack of formatting or any mistakes, but this is from a cellphone.

    I also encountered strides where I tried to use fwrite() to output using the int** variable as the src address.

    One solution was to make use of two malloc() invocations:

    #define HEIGHT 16
    #define WIDTH 16
    .
    .
    .
    //allocate
    int** data = malloc(HEIGHT*sizeof(int**));
    int* realdata = malloc(HEIGHT*WIDTH*sizeof(int));
    //manually index
    for(int i = 0;i<HEIGHT;i++)
     data[i]=&realdata[i*WIDTH];
    
    //populate
    int idx = 0;
    for(int i=0; i < HEIGHT; i++)
     for(int j=0; j < WIDTH; j++)
      data[i][j]=idx++;
    
    //select
    int idx=0;
    for(int i=0; i < HEIGHT; i++){
     for(int j= 0; j < WIDTH; j++)
      printf("%i, ", data[i][j]);
     printf("/n");
    }
    
    //deallocate
    .
    .
    .
    
    0 讨论(0)
  • 2020-12-05 05:59

    If your array dimensions are known at compile time:

    #define ROWS ...
    #define COLS ...
    
    int (*arr)[COLS] = malloc(sizeof *arr * ROWS);
    if (arr) 
    {
      // do stuff with arr[i][j]
      free(arr);
    }
    

    If your array dimensions are not known at compile time, and you are using a C99 compiler or a C2011 compiler that supports variable length arrays:

    size_t rows, cols;
    // assign rows and cols
    int (*arr)[cols] = malloc(sizeof *arr * rows);
    if (arr)
    {
      // do stuff with arr[i][j]
      free(arr);
    }
    

    If your array dimensions are not known at compile time, and you are not using a C99 compiler or a C2011 compiler that supports variable-length arrays:

    size_t rows, cols;
    // assign rows and cols
    int *arr = malloc(sizeof *arr * rows * cols);
    {
      // do stuff with arr[i * rows + j]
      free(arr);
    }
    
    0 讨论(0)
  • 2020-12-05 06:01

    Say you want to dynamically allocate a 2-dimensional integer array of ROWS rows and COLS columns. Then you can first allocate a continuous chunk of ROWS * COLS integers and then manually split it into ROWS rows. Without syntactic sugar, this reads

    int *mem = malloc(ROWS * COLS * sizeof(int));
    int **A = malloc(ROWS * sizeof(int*));
    for(int i = 0; i < ROWS; i++) 
       A[i] = mem + COLS*i;
    // use A[i][j]
    

    and can be done more efficiently by avoiding the multiplication,

    int *mem = malloc(ROWS * COLS * sizeof(int));
    int **A = malloc(ROWS * sizeof(int*));
    A[0] = mem;
    for(int i = 1; i < ROWS; i++) 
       A[i] = A[i-1] + COLS;
    // use A[i][j]
    

    Finally, one could give up the extra pointer altogether,

    int **A = malloc(ROWS * sizeof(int*));
    A[0] = malloc(ROWS * COLS * sizeof(int));
    for(int i = 1; i < ROWS; i++) 
       A[i] = A[i-1] + COLS;
    // use A[i][j]
    

    but there's an important GOTCHA! You would have to be careful to first deallocate A[0] and then A,

    free(A[0]);
    free(A);              // if this were done first, then A[0] would be invalidated
    

    The same idea can be extended to 3- or higher-dimensional arrays, although the code will get messy.

    0 讨论(0)
提交回复
热议问题