Review of Arrays in C

An array is a set number of data items that are all of the same type. Each of these data items is referred to as an element. There are a fixed number of elements in the array, and each element is of the same type, this is as opposed to a structure, which can contain data members of differing types.

We declare an array by placing the type name, followed by the name of the array, and then a number place in brackets. The number indicates the size of the array.

#include <stdio.h>

int main(void){

    long lNums[10];
    char chChars[10];

    printf("a char is %lu byte.\n", sizeof(char));
    printf("our char array is %lu bytes in size.\n", sizeof(chChars));
    printf("there are %lu elements in the chChars array.\n", sizeof(chChars) / sizeof(char));

    printf("a long int is %lu bytes.\n", sizeof(long));
    printf("our long array is %lu bytes in size.\n", sizeof(lNums));
    printf("our long array has %lu elementsin.\n", sizeof(lNums) / sizeof(long));
    return 0;
}

The number in the fixed brackets is called the dimension, it specifies the number of elements we want to store in the array. Each element in the array is accessed by the same name, the name of the array, in addition to the array element’s number.  This number is what is known as an index value. An index value is an integer placed in the square brackets after the array name.

It’s very important to remember that array elements are indexed from 0, not 1. That means the first element is at offset 0, the second element is at offset 1, etc. This is actually conceptually clearer in pointer notation than in array index notation, but array notation is way less of a pain to use, especially when working with multidimensional arrays.

#include <stdio.h>

int main(void){

    int iArray[5];

    iArray[0] = 8;
    iArray[1] = 16;
    iArray[2] = 32;
    iArray[3] = 64;
    iArray[4] = 128;
    //no more elements left! we've used
    //them all up.
    //let's print them out
    
    int *iPtrArray = iArray;
    printf("%d\n", *(iPtrArray+0));
    printf("%d\n", *(iPtrArray+1));
    printf("%d\n", *(iPtrArray+2));
    printf("%d\n", *(iPtrArray+3));
           printf("%d\n", *(iPtrArray+4));

    printf("%d\n", iArray[0]);
    printf("%d\n", iArray[1]);
    printf("%d\n", iArray[2]);
    printf("%d\n", iArray[3]);
    printf("%d\n", iArray[4]);

    return 0;    
    
}

To access a value of an element in an array, we can also place an expression in the square brackets following the array name. As long as the expression resolves to an integer value that falls within the bounds of the array, we are fine.

#include <stdio.h>

int main(void){

    double dNums[5];

    int i = 0;

    dNums[i] = 16.16;
    dNums[++i] = 10.16;
    dNums[i+1] = 88.103;
    dNums[++i + 1] = 104.102;
    dNums[i + 2] = 13.1723;

    for(i = 0; i < 5; i++){
        printf("%f\n", dNums[i]);
    }

    return 0;

}

Remember, when we use an expression to specify the array element the only constraints are that it must produce an integer result and the result must be a legal index value for the array.

For our next program, let’s use an array to store a set of scores that we wish to average.

#include <stdio.h>

int main(void){

    int iScores[10];

    int iCount = 10;

    int iSum = 0;

    double dAvg = 0;

    int i;

    printf("Please enter the scores.\n");
    for(i = 0; i < iCount; i++){
        printf("Score %d of %d:\t", i + 1, iCount);
        scanf("%d ", &iScores[i]);
        iSum += iScores[i];
    }

    dAvg = (double)iSum / iCount;

    for(i = 0; i < iCount; i++){
        printf("%d\t", iScores[i]);
    }
    printf("\nAverage: %f\n", dAvg);
    
    return 0;

}

In the above program, we declare an array of ten integers and then a couple of numbers that we will use for the program. We then will prompt for input using a for loop, and then output the data using another for loop. We use scanf() to accept input from standard input; although in production code we should never use scanf(), it’s fine for our purposes here.

Note that with the for loop we start the count at 0, rather than 1, and use a non-inclusive comparison (< instead of <=). This makes it so we can use the iterator variable for providing the index value for the array.

Numerical Arrays

To set a dimension for a numeric array, we imply place a number inside the brackets to the right of the array name. For exampe, alsArray[5] has an array named alsArray that has five possible elements. If we want to declare an int array, we enter int alsArray[10], thereby declaring an array of type int with 10 elements. To declare a double array, we enter double arrayName[7], thereby declaring an array of double values that can hold up to seven elements.

 #include <stdio.h>

int main(void){

    int theArray[10];

    printf("theArray located at memory address %p\n", theArray);
    printf("which is also the address of the first element %p\n", &theArray[0]);

    return 0;
    
}

Note that the name of the array and the memory address of the first element in the array are, in effect, the same.

To access an element in an array, we use the index number of the element. The index number of an element is the offset from the base address of the array, this offset is calculated by the increasing the memory location by the size of the element stored in the array. What this means to us, practically, is that the index value starts at 0 for the first element of the array. Thus, to access the third element in an array, we use the index value 2, and to access the sixth element in the array, we use the index value 5.

#include <stdio.h>

int main(void){

    int intArray[5];

    printf("intArray[0] is located at %p\n", &intArray[0]);
    printf("intArray[2] is located at %p\n", &intArray[2]);
    printf("intArray[0] has the value %d\n\n", intArray[0]);
    printf("the last element in the array is");
    printf("intArray[4] and is located at %p\n", &intArray[4]);
    printf("and has the value of %d\n", intArray[4]);

    return 0;

}

The values stored in each array element are just junk values – they don’t mean anything, they are just the base 10 representation of whatever binary data happened to have been already in the memory location when it was assigned to the array.

It is easy to place our own values into an array. We simply use the assignment operator, =, in conjunction with the index number of the element we wish to which we want to assign a value.

#include <stdio.h>

int main(void){

 int intArray[3];

 intArray[0] = 1729;
 intArray[1] = 404;
 intArray[2] = 6174;

 printf("first element = %d\n", intArray[0]);
 printf("second element = %d\n", intArray[1]);
 printf("third element = %d\n", intArray[2]); 

 return 0;

}

Since index notation is just a simple way to indicate the offset from the array’s base, we can use pointer arithmetic to access elements in the array as well.

#include <stdio.h>

int main(void){

    int array[3];

    int *ptr = array;

    array[0] = 8088;
    *(ptr+1) = 2600;
    array[2] = 90210;

    printf("first element = %d\n", *(ptr));
    printf("second element = %d\n", ptr[1]);
    printf("third element = %d\n", *(ptr+2));

    return 0;

}

Arrays are often passed to functions in a program. When we pass an array, the address of the array’s base s actually copied and passed to the function being called. This means that, in effect, arrays are passed by reference, not by value, so that any changes we make to the array in the called function will persist beyond its own lifetime.

#include <stdio.h>

void calledFunction(int theArray[]);

int main(void){

 int theArray[3];

 theArray[0] = 47;
 theArray[1] = 73;
 theArray[2] = 1776;

 calledFunction(theArray);
 
 return 0; 

}

void calledFunction(int theArray[]){

 printf("parameter array[0] = %d\n", theArray[0]);
 printf("parameter array[1] = %d\n", theArray[1]);
 //don't forget pointer arithmetic also works
 printf("parameter array[2] = %d\n", *(theArray+2));

}

Remember, the whole array is not passed to a function; rather, the starting address of the array is copied into the corresponding parameter. The upside to this is that any changes made to the array are persistent, and we do not have to tie up system resources copying potentially large arrays. The downside is that the called function has no way of knowing the bounds of the array unless it is explicitly informed of the count. We can let a function know what the array’s limits are by passing it an index value indicating the length of the array.

#include <stdio.h>

//don't forget to subscript the
//array parameter
void populateArray(int array[], int length);

int main(void){

    int theArray[8];
    
    //call the array
    populateArray(theArray, 8);

    printf("theArray[2] = %d\n", theArray[2]);
    printf("theArray[4] = %d\n", theArray[4]);
    printf("theArray[7] = %d\n", theArray[7]);

    return 0;

}

void populateArray(int array[], int length){
    while(--length > 0){
        array[length] = length + 1;
    }
}

There are times, especially when sorting an array, that two elements in the array must be swapped. The key to swapping the two elements is assigning the value of one of the elements to a temporary variable, so that the value will not be lost during the swap.

#include <stdio.h>


#define SIZE 7

void printArray(int nums[]);
void swapInts(int *a, int *b);

int main(void){

    int nums[SIZE] = {47, 1024, 80, 443, 1701, 1138, 161};

    printArray(nums);    

    swapInts(&nums[2], &nums[5]);

    printArray(nums);

    swapInts(&nums[1], &nums[3]);

    printArray(nums);


    return 0;


}

void swapInts(int *a, int *b){
    int temp = *a;
    *a = *b;
    *b = temp;
}

void printArray(int nums[]){
    for(int i = 0; i < SIZE; i++){
        printf("%d", nums[i]);
        if(i < SIZE - 1){
            printf(", ");
        }
    }
    printf("\n");
}

Finally, let’s write a generalized search function that determines whether or not a specific value is stored in an array. Our function in this example can return either one of two values. The default return value is a negative number; since we cannot have a negative index, a negative return value indicates that the function failed to find the number. If the function does find the desired number in the array, it returns the index of that value.

#include <stdio.h>


void printArray(int array[], int bounds);
int searchArray(int array[], int bounds, int value);

int main(void){

 int arrayLength = 8;
 int searchArrayLength = 5;
 int returnValue;

 int array[] = {64134, 74137, 64111, 64131, 74135, 64131, 20016, 64145};
 int searchVals[] = {73, 64131, 1999, 2001, 74137};

 



 printf("This is the array: ");
 printArray(array, arrayLength);

 for(int i = 0; i < searchArrayLength; i++){
 returnValue = searchArray(array, arrayLength, searchVals[i]);
 if(returnValue < 0){
 printf("Value %d not found.\n", searchVals[i]);
 } else {
 printf("Value %d found at index %d\n", searchVals[i], returnValue);
 }
 }

 

 return 0;

}

int searchArray(int array[], int bounds, int value){
 int i = 0;

 while(i < bounds){
 if(array[i]==value){
 //if match is found
 //return index number
 return i;
 } else {
 i++;
 }
 }

 //if no value match is found
 //return -1
 return -1;
}

void printArray(int array[], int bounds){
 int i = -1;
 int lessBounds = bounds - 1;
 while(++i < lessBounds){
 printf("%d, ", array[i]);
 }
 printf("%d\n", array[lessBounds]);

}

Be sure and take a look at my Amazon author’s page at http://www.amazon.com/Big-Als-C-Standard-ebook/dp/B00A4JGE0M