Problems with Arrays

What would this do?

int value[5];
int stuff[100];
...
for(int i=0;i<100;i++) {
        value[i] = 10;
}
for (int i=0;i<10;i++) {
    stuff[i] = 1;
}
cout << "value[0] = " << value[0] << endl;
cout << "value[10] = " << value[10] << endl;

Well, the compiler would say this is fine, you must know what you are doing. But do you? What is going on anyway?

value[0] = 1
value[10] = 10

When we refer to the name value in this example, the compiler looks the name up in its internal table and figures out what address got assigned to this big box of integers - lets say it was location 1004, just for the heck of it.

Now, integers are four small boxes big - actually they take 32 bits each in most systems. So the first integer we put in stuff fills up memory locations 1004, 1005, 1006, and 1007. That corresponds to the first integer in stuff or stuff[0]. The next integer we put in stuff will live at locations 1008, 1009, 1010, and 1011. That container we can access as stuff[1]. Keep this up and we get to stuff[4], the last one we set up in our declaration. This integer lives at locations 1020, 1021, 1022, and 1023. So far, so good.

What lives at location 1024? Based on the way I declared variables, I set up a container named value right after my stuff. The first integer in that new container lives in the next available memory location - you guessed it - at 1024 (and 1025, 1026, and 1027).

But, my loop kept on indexing elements of stuff far past where I have set any container up for that silly stuff! Guess what I am doing in this loop? Killing the contents of value!

This is called over-indexing and array and it is a very bad thing to do (and one of the easiest mistakes in all of programming to make!)

Our mistakes are seldom this obvious, most of the time we zap the first element in the second array by failing to stop our loops right:

int stuff[5];
..
stuff[5] = 0;
...
for(int i=0;i<=5;i=i+1) {
    stuff[i] = 0;
}

This one is just as bad, just not so obvious.

Searching an array

Let’s try another example using arrays. Suppose we wanted to find the biggest value in a bunch of values (like our grades above). Now, we do not know where the biggest number will live. So, we need to look at all the locations and find the biggest one. How do we even start working this out?

Well, we need to loop over all the grades and hunt for the answer!

int grades[10] = {45,77,65,88,99,90,80,50,69,70};
...
for(int i=0;i<10;i=i+1) {
    // is grades[i] biggest?
}

(OK, I changed the first grade to make the hunt a bit more difficult!)

Now, we need to think about our loop. We start off looking at the first grade in the array. Is it the biggest? It is the biggest of all the grades we have looked at so far, so let’s keep that value as the current biggest. If we find anything bigger, we will change our value to that new biggest, and so on. So, here is what we might end up with:

int biggest = grades[0];
for(int i=1;i<10;i=i+1) {
    if(grades[i] > biggest)
        biggest = grades[i];
}
cout << "The biggest value was " << biggest << endl;

Notice that I changed my loop to start with index 1 now, not zero. I also started off storing the value of biggest with the value in grades[0]. Why? Because the first element in the array is the biggest one I have seen so far, I will change my mind later if I see a bigger value in the loop!

The loop looks at each remaining grade in the array and checks to see if any of them is bigger than the biggest I have seen so far. Each time I find a bigger value, I throw away my old value and keep track of this new big guy!

The biggest value was 99

Looks like it worked!

Can we get the smallest at the same time? Sure, use the same approach as before:

int biggest = grades[0];
int smallest = grades[0];
...
for(int i=1;i<10;i=i+1) {
    if(grades[i]>biggest) biggest = grades[i];
    if(grades[i]<smallest) smallest = grades[i];
}
cout << "Big was " << biggest << " and small was " << smallest << endl;
Big was 99 and small was 45

That is enough for this lesson!