Arrays

 

This web page is about arrays - an array is a set of elements - putting elements into an array is a useful way for us humans to "see" a group of elements as a single entity, C allows us to do this, however C doesn`t know how to deal with an array as a single entity - in order to do things with arrays, we have to treat each element in the set as a separate item.

The elements can be anything that C regards as an object - ie, an item that has a memory space allocated to it, that can contain a value. So elements can be numerical constants, variables, pointers, or text - although text based arrays are treated a bit differently to numerical element based arrays.

However the element types cannot be mixed in an array - every element in an array must be of the same type.

Since a fully defined array is itself an object, an array can be built out of elements each one of which is itself an array. This is known as a multidimensional array.

 

Dimensions of arrays

An array can have any number of dimensions - so for example


        2 3 4 5 6

would be a single line array, and


        2 3 4 5 6

        7 8 9 0 1

would be a two line or two dimension array. I don`t think I am going to try to represent a three dimension array on a two dimension display. C doesn`t restrict you to three dimensions, you can have any number - but how we visualise them I am not sure.

Maybe you could visualise a stack of three dimensional arrays that builds with time as a four dimension array, but it`s getting scary !

 

Defining an array

Arrays are defined in a similar way to defining variables, but the size of the array is added as an expression contained in [ ] brackets.


        int array_1[5];

This would define a single row / one dimension array with five elements. A two dimension array would be defined as


        int array_1[5],[2];

This array would be five elements wide, with two rows. A three dimension array is defined as


        int array_1[5],[2],[5];

and so on.

 

Defining the elements

Going back to the original one dimension numerical array -


        int array_1[5];

This defines a single row array with five elements in it. We can also specify the five elements within the definition :


        int array_1[5] = { 2, 3, 4, 5, 6 };

Within the array, the element positions are identified by numbers, counting from the left, and counting up from zero. So in this array, the positions are -


        int array_1[5] = { 2, 3, 4, 5, 6 };
                           
                           |  |  |  |  |

          position         0  1  2  3  4

You can also define the elements within an array after the array itself has been defined, by using the element position in a definition.


        array_1[0] = 2;

        array_1[1] = 3;

        etc

If the size of an array is defined, but not all the elements are given a value, C by default will put in a "0" in each unvalued position.

Defining an element in a two dimension array works just the same way -


        array_1[2],[1] = 9;

This would place the value of 9 in the 3rd column, 2nd row. And so on for higher numbers of dimensions.

 

Text arrays

As mentioned above, arrays where the elements are text are treated a bit differently - each row of a text based array has as the last element the null character - or "\0".

The null character occupies a position - ie, the right most position - and this position has to be included in the expression that indicates the number of elements in the row. So if you want to have 4 text characters in the row, there has to be 5 element positions.


        char char_array[5] = { t, e, x, t };

From this definition, C actually sets up the array -


        char char_array[5] = { t, e, x, t, \0 };

 

Memory allocation for fixed length arrays

Fixed length arrays were the type of arrays that were built into C when it was originally designed, and continued in ANSI C. They are still part of later versions of C such as ISO C99.

When a fixed length array is defined, a block of memory is allocated which is the correct size to contain all the data that the array will contain - even if the values of the data have not been defined.

Although an array is defined in a way that is close to the way in which a variable is defined, an array is not a variable. The array name is not a container that contains the data in the array.

An array name is a name for a memory location. It is the name for the memory location that is occupied by the first element in a single row array, or the element in the first row and first column of a two dimension array.

When an array name is passed down to a function, it is actually the memory location that is passed down.

C knows from the definition of the array how much memory is allocated to the array, so the memory location passed down is the first address of the block of memory addresses that hold the contents of the array.

Fixed length arrays are defined outside any function like global variables are, and they should normally be allocated the storage class of static. The array exists for the whole duration of the programme run time.

 

Memory allocation for variable length arrays

The ISO C99 version of C introduced a different type of array in addition to the original fixed length array - if an array is defined inside a function, it can be defined without giving it a fixed length - this can allow an array to be set up as a variable length array, without a specified length.

Once the length has been subsequently defined in the function, the array length cannot be changed. However the array only exists whilst the function is running.

Once the function has finished running and has exited, the memory allocation ceases to exist. The next time the function is run, the array can be given a different length.

This is therefore using the auto storage class, like a variable defined within a function.

However it appears that this is really only suitable for small arrays. For larger arrays, memory space can be allocated using dynamic memory allocation, which requires a system call via pre-built library functions such as malloc() and calloc().

There is more about dynamic memory allocation in the following web page, about memory.

 

Pointers to arrays

Just like variables, you can set up pointers to arrays - however there are some differences between pointers to variables, and pointers to arrays. You could argue that a pointer to an array is actually a pointer to a pointer.

If you recall, a pointer to a variable is actually a pointer to the memory location that holds the content of the variable. A pointer variable is defined by -


        int var_1 = 100;               // defines the variable var_1

        int *ptr_1;                    /* defines the pointer as pointing 
                                        * to a variable of type int   */

        ptr_1 = &var_1;                /* defines the pointer as pointing
                                        * to the memory location of 
                                        * the variable var_1          */

Then we can also get the pointer to refer to the content of the variable by using the * indirection operator -


        *ptr_1 = 101;                  /* changes the content of the
                                        * variable to 101            */

Now as previously explained, an array name is a name for a memory location, so when creating a pointer to point to an array, there is no need to use the ampersand character - because it is already the memory location of the first element of the array . So whilst the normal assignment of the pointer to the array would look like


        int array_1[5] = { 2, 3, 4, 5, 6 };

        int *ptr_1;

        ptr_1 = &array_1[5];

this can also be written as


        int array_1[5] = { 2, 3, 4, 5, 6 };

        int *ptr_1;

        ptr_1 = array_1;

and this is the same thing.

However the reverse is not allowed. Because ptr_1 is a variable ( a pointer is a particular type of variable ), then the contents of ptr_1 can be set to anything we want to set it to. So


        ptr_1 = array_1;

is a valid statement. But array_1 is not a variable, it is a memory location, so


        array_1 = ptr_1;

is not a valid statement.

 

Storage classes

Fixed length arrays can be assigned to the same four strorage classes that variables can be assigned to. The storage classes are -

⇒   auto
these arrays are local to a block of code or a function, and are discarded once the block of code has run - auto is the default for local arrays, if no storage class identifier is given
⇒   register
these arrays would use a register for storage if the compiler is in a good mood, otherwise are like auto - maybe this is theoretically possible, but would there be enough registers to store an array ?
⇒   static
static is the default for global arrays, and can be used for local arrays, but not variable length ones - static arrays keep their values for the duration of the whole programme, not just for the duration of a block of code
⇒   extern
an extension of static, which allows the array to be "seen" across different files, which are subsequently linked

The storage class for an array is added to the declaration or definition of the array - for example -


        int array_1[5];

        static int array_2[8];

        extern float array-3[10]

 

Time for a programme

To close on arrays, here is a wee programme that illustrates a global fixed length array, and a pointer which points to the array.


        #include <stdio.h>

        int my_array[4] = {2, 3, 4};

        int *ptr_my_ar = my_array;

        int main()

             {

        printf(" \n \n \t the name of the array shows the first address - %p \n",my_array);

        printf(" \n \t the first address - %p \n",&my_array[0]);

        printf(" \n \t the second address - %p \n",&my_array[1]);

        printf(" \n \t the third address - %p \n",&my_array[2]);

        printf(" \n \t content of the pointer ptr_my_ar - %p \n",ptr_my_ar);

        printf(" \n \t contents of the array - %d %d %d \n \n",my_array[0], my_array[1], my_array[2]);

        return(0);

                    }

It compiles fine with gcc, and when run, produces the result


        the name of the array shows the first address - 0x804a014

        the first address - 0x804a014

        the second address - 0x804a018

        the third address - 0x804a01c

        content of the pointer ptr_my_ar - 0x804a014

        contents of the array - 2 3 4

It is interesting to see that gcc has reserved 4 bytes of storage for each integer value, rather than two.

 

 

 

 

 

website design by ron-t

 

website hosting by freevirtualservers.com

 

© 2024   Ron Turner

 

+                                   +  

 

Link to the W3C website.   Link to the W3C website.