Q:

Looping through an array with for gives different results

I'm having a somewhat of a problem with an array in bash. 
Given this array:
 krn=(linux-image-4.15.0-30-generic linux-image-4.15.0-32-generic linux-image-4.15.0-33-generic)

If I use the following for loop to iterate through it, I get different results without changing anything:
1st time:
for krn in ${krn[@]};do echo $krn;done
linux-image-4.15.0-30-generic
linux-image-4.15.0-32-generic
linux-image-4.15.0-33-generic

2nd time:
for krn in ${krn[@]};do echo $krn;done
linux-image-4.15.0-33-generic
linux-image-4.15.0-32-generic
linux-image-4.15.0-33-generic

What am I doing wrong?
If I use a C style for with array lenght, it doesn't have this strange behaviour.
for ((i=0; i<${#krn[@]}; i++)); do echo ${krn[i]};done

A:

Your loop uses krn as the loop variable. This is also the name of the array that you loop over. The shell does not maintain separate name spaces for array variables and non-array variables. 
For each iteration, krn will be set to the current value from the array. This has the effect of modifying the array's first element in every iteration. The loop modifies the array so that the first element will be a copy of the last element after the end of the loop. 
To correct this, choose another name for the loop variable, or for the array. 

Additionally, you should use "${krn[@]}" (the expansion, double quoted) in the loop head as using ${krn[@]} unquoted would split each element on whitespaces (or whatever is in $IFS) and invoke filename globbing on the resulting words.  The same goes for echo "${krn[i]}" in the later loop.
Assuming there is at least one element in the array, the whole loop could alternatively be replaced by
printf '%s\n' "${krn[@]}"

