Dorn już zauważył rozmiar tablicy, ale skoro napisałem list, to go wkleję :-)
C nie jest prostym językiem ze względu na to, że wielu oczywistych pomyłek kompilator nie zgłasza.
masz deklarację
int liczba [9];
to znaczy, że masz 9 elementów w tablicy (nie 10). Elementy w tablicy będę miały indeksy od 0 do 8.
A Twoje pętle przebiegają od 0 do 9. Czyli sięgasz po element liczba[9], który nie istnieje.
Kompilator tego nie zgłosi.
Czemu raz działa, a innym razem nie?
W pamięci zmienna "liczba" - to jest obszar
Kopiuj
9 * sizeof(int) bajtów.
(sizeof(int) podaje Ci rozmiar w bajtach zmiennej typu int. Ile to będzie konkretnie - to zależy od środowiska. W Windowsie 16-bitowym - to były 2 bajty, w Win32 - 4 bajty, na Linuxie - nie wiem).
Załóżmy, że działasz na Win32. Wtedy Twoja zmienna "liczba" - to jest ciągły obszar pamięci o długości 36 bajtów (9 * 4).
Dla kompilatora (i de facto dla Ciebie) - to jest jednolity obszar pamięci (bajtów).
Możesz np. napisać tak:
Kopiuj
char* t=(char*)liczba;
(to się nazywa rzutowanie typów. Zrzutowałeś typ int na typ char. I teraz pod zmienną t masz ten sam obszar pamięci, ale traktowany jak tablicę znaków, czyli upraszczając bajtów).
I dalej możesz spokojnie napisać t[12]=coś tam
W ten sposób do 13 bajtu tego obszaru wpakujesz "coś tam"
Ale - równie dobrze możesz napisać t[1250]=nowa wartość
Kompilator nie mrugnie, a Ty zapakujesz "nową wartość" do zupełnie innego obszaru pamięci. Rozumiesz?
W tym przykładzie dozwolone będzie t[35]=0, bo to jest ostatni bajt w Twoim zarezerwowanym obszarze.
t[36], to jest pierwszy bajt za zarezerwowanym obszarem. Jeśli w Twoim programie w tym miejscu nie ma żadnych istotnych (innych) danych, to nic się nie stanie. Będzie działać i da dobry wynik.
Wracając do int. To działa tak samo jak tablica bajtów, tylko ze kompilator sam "skacze" po bajtach przesuwając miejsce zapisu do położenia index*sizeof(typ)
Czyli jeśli masz:
int tablica[9], to tablica[2]=12 oznacza, że kompilator zapakuje 12 w cztery bajty poczynając od ósmego (faktycznie tylko jeden bajt będzie miłą wartość 12, a kolejne trzy będą zerami).
W twoim programie - w pętlach w pewnym momencie w czasie wykonywania programu dochodzi do sytuacji
suma+=tablica[9];
W tym momencie następuje pobranie czterech bajtów poczynając od 36 pozycji (licząc w bajtach). A tam może być dowolna wartość, bo twoim ostatnim zarezerwowanym bajtem jest komórka 35.
Reszta (działanie lub nie, ewentualne zawieszenia programu i różne dziwne zachowania) to już jest kwestia przypadku. To będzie zależało od tego, co się znajduje w obszarze do którego się odwołujesz, czy tylko czytasz, czy może próbujesz coś zapisać, itd.
W tych programach jest jeszcze jedna sprawa, na którą można zwrócić uwagę.
W wersji z for zmienna licznik jest deklarowana dwa razy. Raz na początku, i potem w pętli for.
Czy tak można, czy nie - to zależy od konkretnej wersji kompilatora. Niektóre na to pozwolą inne wykażą błąd ("zmienna już zadeklarowana").
A niektóre kompilatory mają nawet opcję konfiguracyjną. W każdym razie proponuję unikać takich sytuacji i nie deklarować dwóch zmiennych o tej samej nazwie w ramach jednej funkcji.