0

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; 
} 
9
  • Probably overhead in the malloc call (e.g. embedding address into allocated chunk). Commented Mar 30, 2020 at 17:06
  • 2
    malloc() needs to store the allocation size so that it knows how much to free when you call free(). Commented Mar 30, 2020 at 17:07
  • 4
    More generally, there's no reason to expect sequential calls to malloc() to return contiguous memory blocks. Commented Mar 30, 2020 at 17:08
  • 1
    There is no requirent for malloc to use any logic to its allocation that a caller can make sense of. The 2D array has no gaps by definition. Commented Mar 30, 2020 at 17:09
  • when we are allocating 2d array dynamically why it is not contiguous Commented Mar 30, 2020 at 17:10

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

Comments

1

The comments on your question have the most essential advice - don't worry about where malloc puts your memory. There is no assurance that it will be in any order. It may locate allocations in pursuit of various optimizations or speculations, and may vary from one execution to the next. If nothing else, other memory allocations, calls to free, garbage collection (in languages with GC, that is) between your calls to malloc will affect the location of the next allocation.

This can also vary with compiler, compiler options, OS, etc.

As for the specific reason your allocations have a 16 byte gap, that's impossible to say without more, and likely very deep, insight into your scenario. BTW, you didn't include output of your printf in your question.

But if I had to guess, I'd say the memory manager was aligning the allocations up with memory boundaries...perhaps a 32-byte or 64-byte boundary.

You're allocating 4 * sizeof(int). If an int is 4 bytes on your system, that's 16 bytes. If your malloc likes to line things up to 32 bytes, that might explain the 16-byte gaps you're seeing.

But again...this is just a guess. The simple answer is...you shouldn't care.

But if you DO care for some reason, you probably need to do your own allocation. malloc a much larger chunk of memory, and then manage your own pointers and allocations internally.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.