Vamos a verlo con calma.
En primer lugar al acceder a una cadena como array no estás leyendo carácter por carácter, en realidad lo hace byte por byte.
Al tratarse de ASCII es normal que una cadena sin acentos devuelva la misma cantidad de caracteres que bytes, pero no es así con cadenas multi byte.
Una cadena multi byte ocupa mas de un sólo byte por carácter, mira tu mismo ejemplo corregido.
Código PHP:
$cadena = "día";
echo $cadena[0];
echo $cadena[1];
echo $cadena[2];
echo $cadena[3];
Ahí si imprime "día" tal cual.
El punto inicial como siempre es, ¿y para qué estás tratando de hacer las cosas así?
Si es por ocio mejor olvida lo que te voy a decir, pero en caso contrario puedes usar funciones multi byte.
http://www.php.net/manual/en/book.mbstring.php