views:

109

answers:

5

The output of the application (bottom) is as follows:

Element index number: 0 Element contents: 22
Element index number: 1 Element contents: 22
Element index number: 2 Element contents: 22
Element index number: 3 Element contents: 22
Element index number: 4 Element contents: 22
Element index number: 22 Element contents: 134513712

Why are index elements labeled 5 - 21 missed out? I understand this code could segfault do to the bounds of the array being overflowed, it is designed to do that, I'm not interested in why this code is bad, just why certain indexes are skipped.

#include <stdio.h>
int main(){

int array[5];

int i;
for(i=0; i<10; ++i){
    array[i] = 22;
    printf("Element index number: %d Element contents: %d\n", i, array[i]);
}
return 0;
}
+9  A: 

Once you overflow the allocated memory, you're in "undefined territory". Probably the array write wrote to where the "i" was stored on the stack.

Note that unlike languages like Java and C#, C does no run-time bounds checking, so it's not guaranteed to do anything useful (like segfault) when you overrun an array or string or malloced memory. It's not guaranteed to do anything. It could crash, it could continue to run, it could cause demons to fly out your nose.

Paul Tomblin
Dan Moulding
+7  A: 

What is happening is that when you write to array[5] you are writing to i. They are adjacent on the stack, in memory, so this is the behavior you can expect.

Think about it this way,

you made an array with 5 elements at

int array[5];

in reality, array is just an address. the number in the [] specifies how far past that address to access. So:

  • array[0] 0 ints in memory past address "array"
  • array[1] is 1 ints in memory past address "array" ...
  • array[4] is 4 ints in memory past address "array" (the last int you reserved for array)

so if you get all the way to

  • array[5] is 5 ints in memory past address "array"

There's no bounds checking automatically in C, so its happy to overwrite your own memory. You've put "i" after array[5] in the stack, most likely array[5] is i.

You just set array[5], or i, to 22, hence i is 22. Now that i is 22, your next lookup, into array[i] is really array[22]. This grabs whatever junk happens to be in that location in memory; or if you're lucky, crashes.

Doug T.
"when you write to array[6] you are writing to i" should be 'array[5]', as you correctly write later.
Adriano Varoli Piazza
Note that where array ends and i begins is implementation and architecture dependant, so on a different compiler, different OS version, different OS or different architecture, you could get totally different results.
Paul Tomblin
A: 

Most likely the storage for local variable "i" is located immediately after "array" on the stack, so &array[5] == &i, which means you are assigning 22 to "i" when you assign 22 to array[5].

Lance Richardson
A: 

You've declared an array of 5 ints, but your for loop writes values into 10 entries.

Change

int array[5];

to

int array[10];
rikh
sorry... downvote because you probably didn't even read the question: ...the bounds of the array being overflowed, it is designed to do that, I'm not interested in why this code is bad...
Peter Perháč
+2  A: 

@Doug has it, but let's expand it a bit.

You have array[5] and i as auto variables, so they're allocated on the stack at entry, so you allocate 6 cells: array[0], array[1], ... array[4], and then i.

When you set i to 5, array[i] pointed to the cell on the stack containing i. You then assigned 22 to it. So now i=22, as you printed.

Then you get array[i] or array[22], which is down off the end of the stck; the random value there happens to be that big number.

Charlie Martin
well put. someone's answer needed to add that detail "Then you get array[i] or array[22]..."
Peter Perháč
oops I just added all this, not sure which one of us said it first. +1 to you
Doug T.
We crossed over -- and I +1'd you for the same reason.
Charlie Martin