Skladnia do tworzenia zainicjowanej statycznej tablicy 2D:
int tab[][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}}
int *tab[4] = {{a1, a2, a3, a4}, {a5, a6, a7, a8}};
Te dwa przypadki nie sa sobie rownowazne - w pierwszym przypadku mamy wskaznik do tablicy 2D w drugim przypadku mamy wskaznik do tablicy wskaznikow, ktore moga wskazywac na wiersze.
Do tworzenia niezaincjowanej statycznej tablicy 2D mozesz uzyc:
int tab[2][4];
int *tab[4];
Te dwa przypadki takze nie sa sobie rownowazne (z takiego samego powodu jak poprzednio). Roznia sie od poprzedniego przykladu tym, ze trzeba podac wszystkie wymiary (w pierwszym przykladzie trzeba podac tylko najbardziej "prawy" wymiar i musi byc on staly).
Do tworzenia niezainicjowanej dynamicznej tablicy 2D mozna uzyc:
int (*tab)[4] = new int[n][4]; //Tutaj najbardziej prawy wymiar tez musi byc staly
int **tab = new int*[n];
Te dwa przypadki nie sa sobie rownowazne. W pierszwym mamy wskaznik na dynamiczna tablice 2D w drugim mamy wskaznik do dynamicznej tablicy wskaznikow.
Teraz jak przekazujemy tablice do funkcji:
Takie zapisy:
void fun(int** tab)
void fun(int* tab[])
void fun(int* tab[4]) //4 moze byc dowolna inna liczba
dla odmiany sa sobie rownowazne. Do tych funkcji mozesz przekazac tablice wskaznikow. Natomiast taki zapis:
void fun(int tab[][4]) //trzeba podac najbardziej prawy wymiar
juz nie jest rownowazny poprzednim i oczekuje przekazania tablicy 2D zamiast tablicy wskaznikow.
Podsumowujac tablice dwuwymiarowa i tablica wskaznikow to dwie rozne rzeczy chociaz moga sluzyc do implementacji funkcjonalnie takiego samego kodu. Te rozroznienie musisz uwzgledniac podczas przekazywania obydwu typow tablic do funkcji.