Search code examples
carrayspointersmemorydynamic-memory-allocation

Dynamic memory allocation of 2d array


In this code, while we are dynamically allocating memory for the 2D array, after 4 address why it is taking a gap of 16 bytes but when we are statically allocating 2D array then it does not have such gap.... what is the reason behind this???

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

int main() 
{ 
    int r = 3, c = 4, i, j, count; 

    int stat[r][c];

    int *arr[r]; 
    for (i=0; i<r; i++) 
         arr[i] = (int *)malloc(c * sizeof(int)); 

    // Note that arr[i][j] is same as *(*(arr+i)+j) 
    count = 0; 
    for (i = 0; i <  r; i++) 
      for (j = 0; j < c; j++) 
         arr[i][j] = ++count; // Or *(*(arr+i)+j) = ++count 

    for (i = 0; i <  r; i++) 
      for (j = 0; j < c; j++) 
         printf("%d\n", *(arr+i)+j); 

    printf("\n\n");  
    for (i = 0; i <  r; i++) 
      for (j = 0; j < c; j++) 
         printf("%d\n", *(stat+i)+j); 

    /* Code for further processing and free the  
      dynamically allocated memory */

   return 0; 
} 

Solution

  • Because you are not allocating a 2D array. You are allocating a set of 1D arrays, and those allocations do not have to be contiguous (most malloc implementations reserve some bytes to store the size of the allocated block).

    To dynamically allocate a "true" 2D array where number of rows and columns aren't known until runtime, you'd do something like this:

    stat (*arr)[c] = malloc( sizeof *arr * r );
    

    that would be contiguous like any "normal" 2D array.

    But...

    Strictly speaking, this behavior is undefined - since arr points to a VLA, the sizeof *arr expression must be evaluated at runtime, not at compile time, and arr is not a valid pointer value at that point. I've never seen this fail on any implementation I've used, but that doesn't mean it won't fail somewhere. If c were constant instead, like

    stat (*arr)[3] = malloc( sizeof *arr * r );
    

    then there wouldn't be a problem, and this would be the preferred way to dynamically allocate an Nx3 array.

    If you need all array elements to be contiguous (such that you could traverse the entire array with a pointer or something like that), then the safest option is to allocate your memory as a 1D array:

    stat *arr = malloc( sizeof *arr * r * c );
    

    and compute the offsets manually:

    x = arr[ i * r + j ];
    

    If you want the convenience of 2D notation, you could try creating a pointer and setting to point to the beginning of the array, something like

    stat (*ptr)[c] = (stat (*)[c]) arr;
    

    but that kind of pointer aliasing is also undefined if the pointer types are not compatible, and we've no reason to expect that a pointer to T is compatible with a pointer to an array of T.