The problem is that you're declaring
a
as a 9 byte length variable with 9 characters, so there is no trailing null byte '\0' because there is no space left. That means you have a string that isn't null-terminated.
The declaration of:
char a[9]="abcdefghij";
will result in the allocation of 9 bytes in the stack (because you force it declaring the array of 9 elements) and filled with the string "abcdefhij" without a null byte. No matter how many letters you add to that string, the variable will never contain more than 9 characters, and aditional letters will be discarded (in this case no letter has been discarded, but null-byte was).
Then we have declaration of:
int i=0;
That will reserve 4 aditional bytes in the stack memory. So we have in memory the following contiguous bytes (represented in hexadecimal format, please note 0x61 is letter 'a', 0x62 letter 'b', and so on):
0x61 0x62 0x63 0x64 0x65 0x66 0x67 0x68 0x69 0x00 0x00 0x00 0x00
\_____________________a____________________/ \_________i________/
^
|___ pointer of a[i] when i is equal to 0, at the first iteration.
When you iterate through that array and reach the last position of your string (number 8), while-loop will continue iterating because it isn't null-terminated, causing a buffer overflow at position 9.
So let's take a look what is the situation of the memory at the 9th iteration:
0x61 0x62 0x63 0x64 0x65 0x66 0x67 0x68 0x69 0x08 0x00 0x00 0x00
\_____________________a____________________/ \_________i________/
^
|___ pointer of a[i] when i is equal to 8
That overflow will reach the next variable declared at the stack, in this case
i
, which is an integer (4 bytes).
i
at that moment will have the value of 9.
Showing that graphical:
0x61 0x62 0x63 0x64 0x65 0x66 0x67 0x68 0x69 0x09 0x00 0x00 0x00
\_____________________a____________________/ \_________i________/
^
|___ pointer of a[i] when i is equal to 9
And finally the last iteration will remain like this:
0x61 0x62 0x63 0x64 0x65 0x66 0x67 0x68 0x69 0x10 0x00 0x00 0x00
\_____________________a____________________/ \_________i________/
^
|___ pointer of a[i] when i is 10
At that point the loop will stop because
a[10]
is null, although it's accesing memory that belongs to other variable (
i
).
C language doesn't check any array boundaries (just like Java, C#,... does throwing an exception), and overflowing that boundaries will result in access or overwriting of other memory that could be used by variables, as in this case.
That's the reason why the program is displaying the last '9' and then stops.