Załóżmy taką tablicę:
int tablica[2][3]; // 2 wiersze, 3 kolumny
Takie coś składowane jest w pamięci w porządku row-major czyli wierszami. Dlatego ułożenie elementów tej tablicy w pamięci wyglądać będzie tak:
(0,0) (0,1) (0,2) (1,0) (1,1) (1,2)
Dla przykładu weźmy taką tablicę: (celowo nie zagnieżdżam nawiasów klamrowych)
int tablica[2][3] = {1, 2, 3, 4, 5, 6};
Ułożenie tych elementów w pamięci jest dokładnie takie jak w nawiasach klamrowych (liniowe), ale dla człowieka jej układ jest taki:
1 2 3
4 5 6
Aby obliczyć gdzie znajduje się dany element tablicy dany przez tablica[x][y]
kompilator używa prostego wzoru:
adres_elementu = adres_bazowy + rozmiar_elementu * (x * liczba_kolumn + y);
Adres bazowy dany jest przez nazwę tablicy, rozmiar elementu jest znany (sizeof(int)
), x
oraz y
podał programista, jedyną rzeczą, która musi być jeszcze znana jest liczb kolumn tablicy, czyli właśnie drugi wymiar. Jak widzisz nie ma tu nigdzie informacji o pierwszym wymiarze - jest ona niepotrzebna. Z tego właśnie powodu w deklaracji funkcji wystarczy napisać tak:
void funkcja(int tablica[][3]);
Dodatkowo zauważ, że podczas inicjalizacji drugi wymiar też nie jest potrzebny:
int tablica[][3] = {1, 2, 3, 4, 5, 6};
Elementów jest 6 a drugi wymiar wynosi 3 - jedynym możliwym pierwszym wymiarem jest 2, bo 2*3=6.