Wskaźnik na tablice 2d

0

mógłby ktoś wyjaśnić / podać źródło gdzie jest wyjaśnione czemu tablicy 2d nie mozna przypisać do wskaźnika na wskaźnik.
mam taki mały zgrzyt:
int ** nie moze byc powiazany z int (*)[100]

a co do rozwiązania mojego problemu:
int wsk = (int)tab2d; //chyba działa tylko potem nie mogę się odnosić do wskaźnika w taki sposób: wsk[3][5] ....

z góry dzięki za pomoc

0

wskaźnik na tablicę dwuwymiarową powinien wyglądać np tak:

int ***wsk = &tab2d;
0

Jeżeli masz tablice dwuwymiarową np:
int tb[10][4];
to możesz ją przekazać do funkcji
void f(int tb[][4],int count) { ... }
wywołując następująco:
f(tb,10);

0

Może inaczej...

napisałem taką przykładową funkcje:

void funkcja(int **tablica){
	tablica[0][13] = 2;
} 
 

teraz jak do niej przekazać tablicę??
jak już nie da rady na statycznej to na mallocu mi bugi wywala:
np

int **tab;
tab = (int**)malloc(sizeof(int)*6*6); //tab 6x6
tab[0][3] = 3; //program sie kompiluje ale zakancza sie w tym miejscu ;p
 

w podanym przykladzie jeszcze trzeba jeszcze z 6x malloca uzyć :D

A kwestia tablic statycznych to chyba nie da się i c**** :) -- jestem ciekaw czemu ;p

0

int** to dosłownie jest, czytaj uważnie, coś takiego:
wskaznik na wskaznik na int

jako, że wskaznik na pojedyncza rzecz jest nierozróżnialny od wskaznika na element tablicy, w szczegolnosci tez od wskaznika na pierwszy element tablicy, to w/w mozesz interpretowac i uzywac z ostroznoscia np. jako cala mase roznych rzeczy, poniewaz zarowno pierwsza * jak i druga * moze oznaczac jeden albo wiecej elementow w postaci tablicy. wystapienie dwoch gwiazdek oznacza, ze masz podwojne "odwolanie się przez wskaznik", i że musisz mieć "podwójny łańcuszek" wskaznikow do przejscia dla kazdego końcowego elementu. dwie gwiazdki oznaczaja, ze jednym mallocem w prosty sposob tego nie zalatwisz.

int**tab oznacza "wskaznik na" "jeden lub wiecej elementów będacych" "wskaznikami na" "inty"
tzn. aby utworzyc naturalny obraz takiego czegos, musisz po pierwsze:

   int** tab = (int**)malloc( sizeof(int*) * 5 ); //"wskaznik na" "jeden lub wiecej elementów będacych" == tablica np. pięciu wskaznikow typu int*

po tym, masz tę "zewnetrzny" układ strukturę załatwiony, jednak ile wynosi, po tym co teraz zrobiono, wartosc tab[3] ? to jest jakies int* ale nikt go nie ustawil na nic. ono dopiero co zostalo utworzone jako dzialka w jakiejs tablicy wskaznikow, ale nikt nie zadbal nawet chocby o jego pierwotne wyzerowanie..

   for(int i=0;i<5;++i) tab[i] = (int*)malloc( sizeof(int) * 20 ); //na kazdy int* z tablicy pierwszej, utworz nowa tablice 20elementow

dopiero po tym fakcie, wszystkie nowoutworzone, stablicowane wskazniki int*, zostana "skierowane" na jakas właściwa istniejąca zawartość.
w takim układzie, bedziesz miał tablice [5]ciu wskanikow na tablice [20] intów, czyli tak-jakby, tablice 2D o wymiarach 5x20.

NIE BĘDZIE to jednak tablica 2D.
z samego sposobu konstrukcji wynika, że jest to po prostu pięc tablic 1D 20 elementowych, sprytnie zapamietanych poprzez wskazniki-na-nie w jakiejs innej tablicy 1D.

prawdziwa tablica dwuwymiarowa wyglada tak jak to podal 13sty:

int tab[5][20]

i o dziwo, ma ona dosc dziwny pewnie dla Ciebie typ --- int ()[20]. Zwroc uwage na roznice: jeden wskaznik oraz jeden 'sztywny' wymiar. Uzywajac int * czyli dwoch wskaznikow, luzne wymiary ... wlasnie! luzne wymiary. int* * ma te ceche, że mozesz miec pięc tablic po 20 elementow, ale i mozesz miec 2 po 20 a potem 3 po 10, i tez to trzymac w 100% prawidlowo pod takim samym int* . dodatkowo, "dzięki" temu, że przy zapisie int()[20] ten "koncowy" wymiar jest znany, alokowanie przebiega jednym mallocem i alokuje sie jeden duzy np. 100 elementowy blok intów na całą tablice 2d. jest to jedna tablica, a nie jak w przypadku int* * - pięć tabliczek. ma to i plusy, i minusy, ale pewnie Cie to teraz jeszcze nie interesuje zbytnio.

jeśli chcesz poćwiczyć zapis i używanie tablic iluś-wymiarowych "prawdziwych" i "udawanych", to pamiętaj, że każdy z wymiarów calkowicie niezaleznie od innych moze byc albo "sztywny" albo "luzny"(dynamiczny). Przykład 2D nie wiele pokazuje tak naprawdę, zacznij od gimnastyki z możliwościami tworzenia tablicy 3D - tam wiecej widac 'regularnosci' - http://4programmers.net/C/Tablice_i_wskaźniki,_skomplikowana_składnia - art. jest co prawda w C++ i uzywa 'new' i 'delete' ale na malloc/free jest to banalnie przetlumaczyc

edit: nie da sie statycznymi, poniewaz Twoj typ brzmi int** co już natychmiast mówi, że przynajmniej jeden-"dolny" wymiar musi byc dynamiczny lub udawac dynamiczny.
tak, napisalem "udawac". ostatecznie fakt, że coś tam gdzieś tam spodziewa się wskaznika, wcale nie oznacza, ze musi to byc wskaznik na dynamiczna zawartosc..

int tab[5][20];
int ** tab2 = malloc( 5 * sizeof(int*) );
for(int i = 0; i<5; ++i)
    tab2[i] = &tab[i][0];
....
twojaFunkcja(tab2);
....
free(tab2);

kazdy z pieciu 'wycinkow' oryginalnej tablicy jest "ciągły" w pamięci i jest pełnoprawną tablica 20-elementowa. to znaczy, ze jesli wezmiesz adres na jej pierwszy element, to ten wskanzik bedzie sie zachowywal w 100% identycznie jak wskanzik na swiezo z-mallocowane-20intów. jest to układ prawidłowy i działający poprawnie, jednak nie jest on "naturalny" dla typu int**, tzn. w sensie tego, czego po nim spodziewalby sie typowy sredniobiegły programista.

ah, no i zachowuje sie "identycznie" z ta tylko drobną roznica, właśnie jest to tylko jedna tablica, jeden malloc, wiec i takze tylko jeden free. lepiej nie probowac free'owac poszczegolnych 'kawaleczkow' oryginalnej tablicy, poniewaz byl to oryginalnie jeden duzy obszar pamieci, a ze zwolnienie "kawałka" obszaru pamięci nie jest mozliwe, to efekt takiego np. free(tab2[2]) będzie nieprzyjemny. heh, tym bardziej, ze w/w mój przykład tworzyl oryginalne TAB na stosie, wiec proba takiego free bedzie jeszcze mniej przyjemna dla programu.

0

Solidna rzetelna odpowiedź - wielkie dzięki nie mam pytań (na tą chwile).

1 użytkowników online, w tym zalogowanych: 0, gości: 1