# More on Arrays, Pointers and Malloc

## Multidimensional Arrays

The elements of aai[4][2] are stored in memory in the following order.

aai[0][0]aai[0][1]aai[1][0]aai[1][1]
aai[2][0]aai[2][1]aai[3][0]aai[3][1]

*aai is of type int[]. Note that:-

```         aai[1][2] == *( (aai[1])+2) == *(*(aai+1)+2)
```

and that numerically

```         aai == aai[0] == &aai[0][0]
```

*aai can be used as a pointer to the first element even though it is of type `array 4 of int' because it becomes `pointer to int' when used where a value is needed.

But *aai is not equivalent to a pointer. For example, you can't change its value. This distinction can easily and dangerously be blurred in multi-file situations illustrated in the following example. In

```    extern int *foo;
```

foo is a variable of type pointer to int. foo's type is complete, (sizeof foo) is allowed. You can assign to foo. But given

```    extern int baz[];
```

baz is a variable of type `array UNKNOWN-SIZE of int'. This is an `incomplete' type, you can't take (sizeof baz). You cannot assign to baz, and although baz will decay into a pointer in most contexts, it is not possible for (baz == NULL) ever to be true.

The compiler will allow you to mix the array/pointer notation and will get it right, but it needs to know what the reality is. Once you declare the array/pointer correctly, you can then access it either way.

## realloc

Suppose we have a simple array, and a subfunction for adding items to it:

```#define MAXELTS 100

int array[MAXELTS];
int num_of_elements = 0;

install(int x)
{
if(num_of_elements >= MAXELTS){
fprintf(stderr, "too many elements (max %d)\n", MAXELTS);
exit(1);
}
array[num_of_elements++] = x;
}
```

Let's see how easy it is to remove the arbitrary limitation in this code, by dynamically re-allocating the array:

```#include <stdlib.h>

int *array = NULL;
int nalloc = 0;
int num_of_elements = 0;

install(x)
int x;
{
if(num_of_elements >= nalloc){
/* We're out of space. Reallocate with space for 10 more ints */
nalloc += 10;
array = (int *)realloc((char *)array, nalloc * sizeof(int));
if(array == NULL){
fprintf(stderr, "out of memory with %d elements\n",
num_of_elements);
exit(1);
}
}

array[num_of_elements++] = x;
}
```

If you want to be true-blue ANSI, use size_t for nalloc and num_of_elements.

When dynamically allocating a multidimensional array, it is usually best to allocate an array of pointers, and then initialize each pointer to a dynamically-allocated ``row''. The resulting ``ragged" array can save space, although it is not necessarily contiguous in memory as a real array would be. Here is a two-dimensional example:

```     /* create an array of pointers */
int **array = (int **)malloc(nrows * sizeof(int *));
if (array == NULL){
fprintf(stderr,"Out of memory\n");
exit(1);
}

for(i = 0; i < nrows; i++){
/* create space for an array of ints */
array[i] = (int *)malloc(ncolumns * sizeof(int));
if (array[i] == NULL){
fprintf(stderr,"Out of memory\n");
exit(1);
}
}
```

You can keep the array's contents contiguous, while making later reallocation of individual rows difficult, with a bit of explicit pointer arithmetic:

```     int **array = (int **)malloc(nrows * sizeof(int *));
if (array == NULL){
fprintf(stderr,"Out of memory\n");
exit(1);
}

array[0] = (int *)malloc(nrows * ncolumns * sizeof(int));
if (array[0] == NULL){
fprintf(stderr,"Out of memory\n");
exit(1);
}

for(i = 1; i < nrows; i++)
array[i] = array[0] + i * ncolumns;
```

In either case, the elements of the dynamic array can be accessed with normal-looking array subscripts: array[i][j].

If the double indirection implied by the above schemes is for some reason unacceptable, you can simulate a two-dimensional array with a single, dynamically-allocated one-dimensional array:

```     int *array = (int *)malloc(nrows * ncolumns * sizeof(int));
```

However, you must now perform subscript calculations manually, accessing the i,j th element with array[i * ncolumns + j].

• © Cambridge University, Engineering Department, Trumpington Street, Cambridge CB2 1PZ, UK (map)
Tel: +44 1223 332600, Fax: +44 1223 332662