2

reading a few articles on dynamic memory allocation for multidimensional arrays in c, I came across the following code snippet: (article link)

#define COLS 5

int (*rptr)[COLS];

    int main(void)
        {
            int nrows = 10;
            int row, col;
            rptr = malloc(nrows * COLS * sizeof(int));
            for (row = 0; row < nrows; row++)
              for (col = 0; col < COLS; col++)
                    rptr[row][col] = 17;
            return 0;
        }

Here, a multidimensinal array is defined as int (*rptr)[COLS] and then dynamically linked to malloc(nrows * COLS * sizeof(int)).

Now the question is that how does the pointing work, eg: if the pointing address start from 100,101,102...etc

(assuming int takes 1 byte for simplicity)

rptr[0] points to ->  100 
rptr[1] points to ->  105 

Does the compiler internally link the address accordingly based on the column size as soon as malloc(nrows * COLS * sizeof(int)) is executed?

Thanks

Akash
  • 4,956
  • 11
  • 42
  • 70
  • 1
    If you have a modern C compiler (C99 will do) you can do the allocation much simpler, namely `int (*rptr)[nrows] = malloc(sizeof(int[nrows][ncols]));` where `nrows` and `ncols` can be variables. – Jens Gustedt Jan 04 '12 at 11:40
  • I think the question is nearly identical to http://stackoverflow.com/questions/917783/how-do-i-work-with-dynamic-multi-dimensional-arrays-in-c (How do I work with dynamic multi-dimensional arrays in C?) – Adriaan Jan 04 '12 at 11:50

1 Answers1

4

Consider this ordinary array allocation:

int* a = malloc(sizeof(int) * 10);

The type "int*" is of course a pointer to an int, and sizeof(*a) == sizeof(int). When we do a[3], this is converted to:

*(a + 3)

which (assuming sizeof(long)==sizeof(void*)) dereferences the address:

(long)a + 3*sizeof(*a) == (long)a + 3*sizeof(int)

The way to think about your sample code is that the type "int (*rptr)[COLS]" is a pointer to a (static, one dimensional) int array of size COLS. In other words, sizeof(*rptr) == COLS * sizeof(int). However, just as with the "int *", we can allocate an array of these fixed-size one-dimensional array objects. The indexing "rptr[row]" gets converted to:

*(rptr + row)

which dereferences the address:

(long)rptr + row*sizeof(*rptr) == (long)rptr + row*COLS*sizeof(int)

The resulting type is "int [COLS]", so it can be indexed into again by "[col]". The address calculation ends up being precisely what you want:

(long)rptr + row*COLS*sizeof(int) + col*sizeof(int)

This solution is mentioned at http://c-faq.com/aryptr/dynmuldimary.html, and only works if the number of columns (or in general, all but the first dimension) is fixed at compile time. The syntax gets a bit messy as the number of dimensions increases. If you need more than one dimension to be determined dynamically at runtime, see that page for other strategies.

Chiara Coetzee
  • 4,201
  • 1
  • 24
  • 20