Static arrays reserve storage for the duration of the program and are of a fixed size.
C supports static multi dimensional arrays with the following syntax.
main()
{
int Table[4][3];
/* Table has 4 rows of 3 columns
*
* Table
* -----------------
* | 0,0 | 0,1 | 0,2 |
* -----------------
* | 1,0 | 1,1 | 1,2 |
* -----------------
* | 2,0 | 2,1 | 2,2 |
* -----------------
* | 3,0 | 3,1 | 3,2 |
* -----------------
*/
}
|
This example creates 4 rows of 3 columns, the elements can be accessed by specifing offsets as shown below.
#include <stdio.h>
main()
{
int Table[4][3];
/* Table has 4 rows of 3 columns
*
* Table
* -----------------
* | 0,0 | 0,1 | 0,2 |
* |-----------------|
* | 1,0 | 1,1 | 1,2 |
* |-----------------|
* | 2,0 | 2,1 | 2,2 |
* |-----------------|
* | 3,0 | 3,1 | 3,2 |
* -----------------
*/
/* Assign some values. */
Table[0][0] = 10; /* The first column of the first row. */
Table[1][0] = 20; /* First cell of the second row. */
Table[3][2] = 30; /* Last Column of the last row. */
printf("Last cell of the last row is %d\n", Table[3][2]);
}
|
The array is actually sored in sequential memory as shown below.
Table[0][0] Table[1][0] Table[2][0] Table[3][0]
| | | |
V V V V
--------------------------------------------------------------------------
| 0,0 | 0,1 | 0,2 || 1,0 | 1,1 | 1,2 || 2,0 | 2,1 | 2,2 || 3,0 | 3,1 | 3,2 |
--------------------------------------------------------------------------
|
Being aware of this fact highlights an important feature within C. The right most index always increaments fastest. This is handy when dealing with strings in arrays and is the opposite way to Fortran.
Also, please note that C is not restricted to 2 dimensional arrays. Any number of dimensions are possible, but it sometimes gets hard to think beond 3.
main()
{
int Table[2][4][3];
/* Table has 2 layers of 4 rows of 3 columns
*
* Table
* -----------------------
* | 0,0,0 | 0,0,1 | 0,0,2 |
* |-----------------------|
* | 0,1, -----------------------
* |-----| 1,0,0 | 1,0,1 | 1,0,2 |
* | 0,2 |-----------------------|
* |-----| 1,1,0 | 1,1,1 | 1,1,2 |
* | 0,3 |-----------------------|
* -----| 1,2,0 | 1,2,1 | 1,2,2 |
* |-----------------------|
* | 1,3,0 | 1,3,1 | 1,3,2 |
* -----------------------
*/
}
|
The same concepts still apply. The array is still held in sequential memory and the right most index in incremented fastest.
The examples and concepts above are fine for small arrays but are not pactical for large arrays or for arrays of unknown size. Dynamic arrays get around these short commings.
To understand the concepts that follow, you need to be clear on pointers and more specifically pointers to pointers.
The above examples allocated a block of memory at run time and did not free it until the program ended.
With dynamic arrays, you can create the array when it is required and then remove it when you are finished with it. To get warmed up, here is an example that looks at single dimensional arrays.
#include <stdlib.h>
main()
{
int *Scores=NULL; /* Define a pointer to integer. */
int NumOfScores = 3; /* Size of the array (3 columns) */
int Count;
/*
* At this point Scores is a pointer to NULL.
*
* Scores
* -----
* | 0 |
* -----
*/
/* Create the array. */
Scores = (int *)malloc(NumOfScores * sizeof(int));
/*
* Now Scores points to some reserved memory.
*
* Scores *Scores
* ----- -----------------
* | 268 |--->| | | |
* ----- -----------------
*/
/* Initalise the array. */
for (Count=0; Count < NumOfScores; Count++)
{
*(Scores+Count) = 0;
}
/*
* The reserved memory now has known values.
*
* Scores *Scores
* ----- -----------------
* | 268 |--->| 0 | 0 | 0 |
* ----- -----------------
*/
/* Alter the contents of the array using various syntax. */
*Scores = 10;
*(Scores+1) = 20;
Scores[2] = 30;
/*
* The reserved memory has been altered.
*
* Scores *Scores
* ----- -----------------
* | 268 |--->| 10 | 20 | 30 |
* ----- -----------------
*/
free(Scores);
/*
* The reserved memory has been returned to the heap
* but the pointer remains.
*
* Scores
* -----
* | 268 |
* -----
*/
}
|
C does not have a traditional concept of multi dimensional arrays. Instead, it uses a concept of pointers to pointers, this allows us to build several single dimensional arrays which (as a whole) can be seen as a 2 dimensional array.
Consider this program.
#include <stdlib.h>
main()
{
int *Score1=NULL; /* Define a pointer to integer. */
int *Score2=NULL; /* Define a pointer to integer. */
int NumOfScores = 3; /* Size of the array (3 columns) */
int Count;
/*
* Score1 and Score2 a point to NULL.
*
* Score1
* -----
* | 0 |
* -----
*
* Score2
* -----
* | 0 |
* -----
*/
/* Create two arrays. */
Score1 = (int *)malloc(NumOfScores * sizeof(int));
Score2 = (int *)malloc(NumOfScores * sizeof(int));
/*
* Now Score1 and Score2 point to some reserved memory.
*
* Score1 *Score1
* ----- -----------------
* | 268 |--->| | | |
* ----- -----------------
*
* Score2 *Score2
* ----- -----------------
* | 879 |--->| | | |
* ----- -----------------
*/
}
|
The program creates 2 single dimension arrays but they are not connected to each other. This connection can be made with a pointer to a pointer as shown in the next example.
#include <stdlib.h>
main()
{
int **Score=NULL; /* Define a pointer to a pointer to integer. */
int NumOfScores = 3; /* Size of the array (3 columns) */
int Count;
/*
* Score points to NULL.
*
* Score
* -----
* | 0 |
* -----
*
*/
/* Create an array of two pointers. */
Score = (int **)malloc(2 * sizeof(int *));
/*
* Score points to some reserved memory.
*
* Score *Score
* ----- -----------
* | 268 |--->| | |
* ----- -----------
*
*/
/* Create the first array of integers. */
*Score = (int *)malloc(NumOfScores * sizeof(int));
/*
* Score *Score
* ----- -----------
* | 268 |--->| 432 | |
* ----- -----------
* |
* | **Score
* | -----------------
* ---------->| | | |
* -----------------
*
*/
/* Create the second array of integers. */
*(Score+1) = (int *)malloc(NumOfScores * sizeof(int));
/*
* Score *Score
* ----- -----------
* | 268 |--->| 432 | 735 |
* ----- -----------
* | | *(*Score+1)
* | | **Score
* | | -----------------
* ---------->| | | |
* | -----------------
* |
* | **(Score+1)
* | -----------------
* ----->| | | |
* -----------------
*
*/
/* Now we can start using the array. */
**Score = 10;
*(*Score+1) = 20;
**(Score+1) = 30;
/*
* Score *Score
* ----- -----------
* | 268 |--->| 432 | 735 |
* ----- -----------
* | | *(*Score+1)
* | | **Score
* | | -----------------
* ---------->| 10 | 20 | |
* | -----------------
* |
* | **(Score+1)
* | -----------------
* ----->| 30 | | |
* -----------------
*
*/
}
|
So far, the array Scores has been accessed via pointer notation which is a little messy. We can improve the readability of the code by using array notation as shown in the next example.
#include <stdlib.h>
main()
{
int **Score=NULL; /* Define a pointer to a pointer to integer. */
int NumOfScores = 3; /* Size of the array (3 columns) */
/*
* Score points to NULL.
*
* Score
* -----
* | 0 |
* -----
*
*/
/* Create an array of two pointers. */
Score = (int **)malloc(2 * sizeof(int *));
/*
* Score points to some reserved memory.
*
* Score *Score
* ----- -----------
* | 268 |--->| | |
* ----- -----------
*
*/
/* Create the first array of integers. */
*Score = (int *)malloc(NumOfScores * sizeof(int));
/*
* *Score points to some reserved memory.
*
* Score *Score
* ----- -----------
* | 268 |--->| 432 | |
* ----- -----------
* |
* | **Score
* | -----------------
* ---------->| | | |
* -----------------
*
*/
/* Create the second array of integers. */
*(Score+1) = (int *)malloc(NumOfScores * sizeof(int));
/*
* *(Score+1) points to some reserved memory.
*
* Score *Score
* ----- -----------
* | 268 |--->| 432 | 735 |
* ----- -----------
* | | **Score
* | | *(*Score+1)
* | | -----------------
* ---------->| | | |
* | -----------------
* |
* | **(Score+1)
* | -----------------
* ----->| | | |
* -----------------
*
*/
/* Now we can start using the
|
Result! we have a two dimensional array!!!! Unfortuanatly there is a little bit more to take on board.
Creating the array in the previous examples was a little complicated but was required to explain the concepts. There is a better way to create the array by inverting the allocation sequence. Instead of building the array from the pointers, we could reserve enough memory for th whole array and then calculate the pointer offests. An example follows.
#include <stdlib.h>
main()
{
int **Score = NULL; /* Define a pointer to a pointer to integer. */
int *Temp = NULL; /* Define a pointer to integers. */
int NumOfScores = 3; /* Size of the array (3 columns) */
/*
* Score points to an array of pointers.
*
* Score
* -----
* | 0 |
* -----
*
* Temp
* -----
* | 0 |
* -----
*
*/
/* Create the array of pointers and an array of integers */
Score = (int **)malloc(2 * sizeof(int *));
Temp = (int *)malloc(2 * NumOfScores * sizeof(int));
/*
* Score *Score
* ----- -----------
* | 268 |--->| | |
* ----- -----------
*
* Temp
* ----- ----------------- -----------------
* | 456 |--->| | | || | | |
* ----- ----------------- -----------------
*
*/
/* Now calculate the offsets into Temp and store
* in Score
*/
Score[0] = Temp;
Score[1] = Temp+NumOfScores;
/*
* Score *Score
* ----- -----------
* | 268 |--->| 456 | 459 |
* ----- -----------
* | |
* | |
* | ------------
* | |
* Temp V V
* ----- ----------------- -----------------
* | 456 |--->| | | || | | |
* ----- ----------------- -----------------
*
* Another way of looking at this is
*
* Temp
* -----
* | 456 |
* -----
* |
* Score *Score V
* ----- -----
* | 268 |--->| 456 | ------>
* ----- -----
* | 459 | ------>
* -----
*
*
* A TWO DIMENSIONAL ARRAY!!!
*/
}
|
I hope you can see that we have achived the the same goal as above and created a 2 dimentional array. This method has several advantages.
#include <stdlib.h>
main()
{
int ***Score = NULL; /* Define a pointer to a pointer to a pointer to integer. */
int **Temp1 = NULL; /* Define a pointer to a pointer to integers. */
int *Temp2 = NULL; /* Define a pointer to integers. */
int NumOfScores = 3; /* Size of the array (3 columns) */
/*
* Score
* -----
* | 0 |
* -----
*
* Temp1
* -----
* | 0 |
* -----
*
* Temp2
* -----
* | 0 |
* -----
*/
/* Create the array of pointers and an array of integers */
Score = (int ***)malloc(2 * sizeof(int *));
Temp1 = (int **)malloc(2 * 2 * sizeof(int *));
Temp2 = (int *)malloc(2 * 2 * NumOfScores * sizeof(int));
/*
* Score *Score
* ----- -----------
* | 268 |--->| | |
* ----- -----------
*
* Temp1 *Temp1
* ----- ----------- -----------
* | 954 |--->| | || | |
* ----- ----------- -----------
*
* Temp2 *Temp2
* ----- ----------------- ----------------- ----------------- -----------------
* | 456 |--->| | | || | | || | | || | | |
* ----- ----------------- ----------------- ----------------- -----------------
*
*/
/*
* Now calculate the offsets
*/
Score[0] = Temp1;
Score[1] = Temp1+2;
Score[0][0] = Temp2; /* Score[0][0] == Temp1[0] */
Score[0][1] = Temp2+NumOfScores; /* Score[0][1] == Temp1[1] */
Score[1][0] = Temp2+(NumOfScores*2); /* Score[1][0] == Temp1[2] */
Score[0][1] = Temp2+(NumOfScores*3); /* Score[1][1] == Temp1[3] */
/*
* Score *Score
* ----- -----------
* | 268 |--->| 954 | 956 |
* ----- -----------
* | |
* | |
* | ------
* | |
* Temp1 V V
* ----- ----------- -----------
* | 954 |--->| 456 | 459 || 462 | 465 |
* ----- ----------- -----------
* | | | |
* | | | |
* | | | |
* | | | -------------------------------------
* | | | |
* | | ------------------------ |
* | | | |
* | ------------- | |
* | | | |
* Temp2 V V V V
* ----- ----------------- ----------------- ----------------- -----------------
* | 456 |--->| | | || | | || | | || | | |
* ----- ----------------- ----------------- ----------------- -----------------
*
*/
}
|
Although the array is layed out as above in memory, it can be thought of as looking like this.
------- ---------- ------------- -----------------------------------
| Score |-->| Score[0] |----->| Score[0][0] | --->| [0][0][0] | [0][0][1] | [0][0][2] |
------- |----------| |-------------| |-----------------------------------|
| Score[1] |-- | Score[0][1] | --->| [0][1][0] | [0][1][1] | [0][1][2] |
---------- | |-------------| -----------------------------------
-->| Score[1][0] | --- -----------------------------------
|-------------| |--->| [1][0][0] | [1][0][1] | [1][0][2] |
| Score[1][1] | -- |-----------------------------------|
------------- |---->| [1][1][0] | [1][1][1] | [1][1][2] |
-----------------------------------
|
Although the picture is a bit crappy, I hope you can see that a 3 dimensional array has been created and it is possible to create an array with any number of dimensions.
| Top | Master Index | Keywords | Functions |