Wskazniki - wielowymiarowe tablice.

0

Witam, powracam z nowymi problemami :(
Czytam o wskaznikach i ich relacjach z tablicami. Z tego co rozumiem, tablica "int a[5]" jest wskaznikiem na pierwszy element tej tablicy. W 2-wymiarowej tablicy "int a[2][5]" napisanie "a[0]" zwraca wskaznik na pierwszy "rzad" tej tablicy, czy tez na pierwszy element, ktory jest tablica. Mam jednak problem z odcyfrowaniem ponizszego przykladu z ksiazki:

int ROWS = 2, COLS = 5, a[ROWS][COLS], (*p)[COLS], i;
for (p = &a[0]; p < &[ROWS]; p++) {
	(*p)[i] = 0;
}

Pomijajac kwestie pre i postinkrementacji (ktorej jestem teraz swiadom, dzieki): "p" jest wskaznikiem na tablice liczb calkowitych o rozmiarze "COLS". Zakladam wiec, ze "p++" przesunie wskaznik wlasnie o rozmiar takiej tablicy? Co jednak oznacza "p = &a[0]"? Samo "a[0]" to pobranie elementu zerowego tablicy, czyli w tym wypadku tablicy. Dokladniej - wskaznika na pierwszy element tej "wewnetrznej" tablicy. Nastepnie na tym wskazniku uzywamy operatora "&" - ktory zwraca nam adres... wskaznika?

Porownalem adresy i byly takie same dla "a[0]" i "&a[0]", ale nie moglem uzywach tych dwoch wyrazen zamiennie.

Moglby ktos rozpisac, krok po kroku, ktore zmienne maja jakie wartosci i dlaczego? Wedlug autora ten kawalek kodu ma zerowac i-ta kolumne.

0

jak na mój gust to trochę mało kodu, jaką wartość przyjmuje i?

ucze_sie_c napisał(a):

Co jednak oznacza "p = &a[0]"?

p jest wskaźnikiem na element natomiast &a[0] jest adresem elementu a[0], więc przypisywany jest adres tego elementu do wskaźnika p.

ucze_sie_c napisał(a):

Porownalem adresy i byly takie same dla "a[0]" i "&a[0]", ale nie moglem uzywach tych dwoch wyrazen zamiennie.

a[0] jest 1 elementem tablicy a, natomiast &a[0] jest adresem tego elementu. To tak jakbyś miał w jednym kartke papieru, a w drugim pokazywał palcem gdzie ona leży.

ucze_sie_c napisał(a):

Pomijajac kwestie pre i postinkrementacji (ktorej jestem teraz swiadom, dzieki): "p" jest wskaznikiem na tablice liczb calkowitych o rozmiarze "COLS". Zakladam wiec, ze "p++" przesunie wskaznik wlasnie o rozmiar takiej tablicy?

(*p) to na początku 1 element ,
(*p+1) drugi element

Rzadko programuje w C, ale wydaje mi się, że mam rację. Polecam debugger i przeanalizowanie krok po kroku co przyjmują zmienne.

0

W takich przypadkach piszesz sobie programik testowy typu:

#include <stdio.h>

int main()
  {
   int ROWS=7,COLS=5,a[ROWS][COLS],(*p)[COLS],i=3,y,x;
   for(y=0;y<ROWS;++y) for(x=0;x<COLS;++x) a[y][x]=10*(y+1)+x+1;
   for(y=0;y<ROWS;++y,printf("\n")) for(x=0;x<COLS;++x) printf("%3d",a[y][x]);
   printf("\n");
   for(p=&a[0];p<&a[ROWS];++p)
     {
      printf("%p %u %u\n",(void*)p,(unsigned)(void*)p,COLS*sizeof(int)+(unsigned)(void*)p);
      (*p)[i]=0;
     }
   printf("\n");
   for(y=0;y<ROWS;++y,printf("\n")) for(x=0;x<COLS;++x) printf("%3d",a[y][x]);
   return 0;
  }

http://ideone.com/LTQwTC Trochę UB przy wydruku ale wyjaśnia co tam się dzieje i o ile się zwiększa to p

0

@feni000: "&a[0]" jest adresem elementu a[0]" - tak, ale sam element a[0] to wskaznik poniewaz tablica jest dwuwymiarowa, czyli adres wskaznika?
Moze tak: mam tablice "int a[2][5];" a[0][0] bedzie elementem pierwszym typu int. a[0] bedzie... pierwsza tablica chyba. Czyli wskaznikiem na element pierwszej tablicy. Uzycie "&" na wskazniku daje nam adres tego wskaznika?

Z kolei "(*p+1) to drugi element" - nie wiem do czego to przypiac, w kodzie nie widze czegos takiego. Kazdy element jest tablica, a tablica jest wskaznikiem na pierwszy element. Drugi element bedzie o "typ-wskaznika" po pierwszym?

@_13th_Dragon: dzieki, ale przeceniles mnie - nie potrafie przeczytac ze zrozumieniem drugiego printf()
Widze wydruk i wartosci, ale nie umiem na ich podstawie wydedukowac zasady dzialania :/
Widze, ze "p" rosnie "o 14" w pierwszej kolumnie, ale niewiele mi to mowi. 14 czego? Zakladajac "int" to 4 bajty i "p" zadeklarowany jako wskaznik na tablice o rozmiarze COLS czyli 5, przeskok powinien byc o 20 bajtow? W drugiej i trzeciej kolumnie widze przeskoki "o 20".

0

Chyba cos pomieszalem. Dwuwymiarowa tablica to tablica wskaznikow? Czyli wskaznik na obszar pamieci ktorego elementami sa po kolei wskazniki? Jesli tak, to:

int a[2][3], *p;
p = a; // p jest teraz wskaznikiem na pierwszy element dwywymiarowej tablicy,
	 //wiec i pierwszej jednowymiarowej tablicy?
p = a[0] // p jest wskaznikiem na wskaznik do pierwszego elementu jednowymiarowej tablicy?
p = &a[0] // p dostaje adres wskaznika do pierwszego elementu, ale to to samo
		//co robi poprzednia linia?
0
ucze_sie_c napisał(a):

Chyba cos pomieszalem.

  • mogłeś to nie pisać, sami widzimy.
ucze_sie_c napisał(a):

Dwuwymiarowa tablica to tablica wskaznikow?

  • Dynamiczna - jednoznacznie tak, statyczna - jednoznacznie nie.
ucze_sie_c napisał(a):
int a[2][3],*p;
  • tu masz już zupełnie inną deklaracje tego p
    W związku z czym operacje p=a; oraz p=&a[0][0] - zrobią to samo, p - wskazuje na pierwszy element pierwszego wiersza.
    Natomiast operacje p=a[0], p=&a[0] - też zrobią to samo - błąd kompilacji.
0

Czemu statyczna nie? Nazwa tablicy to wskaznik na pierwszy element tablicy, a kazdy element dwywymiarowej tablicy to tablica - czyli znow wskaznik na pierwszy element tablicy (tym razem tej wewnetrznej). Nie tak? :/

0

W przypadku statycznej - owszem, kazdy element tablicy to tablica
W przypadku dynamicznej - owszem, kazdy element tablicy to wskaźnik
Statyczna - cała jest w jednym kawałku pamięci
Dynamiczna - zapisana w y+1 fragmentach, gdzie y to ilość wierszy
Owszem wskaźnik może być używany jako tablica i vice versa, zaś to nie to samo.

0

Nie jestem chyba blizej zrozumienia :/
Wracajac do pierwszego kawalka kodu: "p = &a[0]". Zgodnie z tabela priorytetow operatorow "&a[0] = (&(a[0]))".

  1. samo "a" to wskaznik na pierwszy element dwuwymiarowej tablicy.
  2. "a[0]" to wskaznik na pierwszy element tablicy "wewnetrznej" - czyli znow wskaznik. Czyli "a" to wskaznik na wskaznik?
  3. "&a[0]" to adres wskaznika? Czy to mi daje adres ktory wskaznik "a[0]" zawiera? Czy adres tego wskaznika? Jak sie ma adres wskaznika na pierwszy element tablicy a[0] do adresu ktory ten wskaznik przechowuje? Gdy drukuje wartosci obu - sa takie same, ale czemu? Adres wewnetrznej tablicy to jedno, a adres wskaznika ktory wskazuje na pierwszy element wewnetrznej tablicy to co innego.
0

Ad 1. NIE!
Ad 2. NIE!
Ad 3. NIE!

samo A to tablica dwuwymiarowa, owszem kompilator da rady skonwertować to na adres pierwszego elementu z pierwszego wiersza
a[0] to pierwszy wiersz tablicy dwuwymiarowej, owszem kompilator da rady skonwertować to na adres pierwszego elementu
&a[0] to adres pierwszego wiersza tablicy dwuwymiarowej.

ucze_sie_c napisał(a):

Gdy drukuje wartosci obu - sa takie same, ale czemu?
Obu trzech? Bo cała tablica zaczyna się w tym samym miejscu co pierwszy wiersz tej tablicy i co pierwszy element pierwszego wiersza.

ucze_sie_c napisał(a):

Adres wewnetrznej tablicy to jedno, a adres wskaznika ktory wskazuje na pierwszy element wewnetrznej tablicy to co innego.
To są jakieś majaczenia.

0

Ok... "a[0]" to pierwszy wiersz tablicy dwuwymiarowej, ale jakie kompilator ma pojecie o wierszach? Chyba zadne, my tak to nazywamy dla "wygody". Dla kompilatora ten wiersz to adres pierwszego elementu tego wiersza (zgaduje, ze to + informacje o typie i dlugosci).

"&a[0]" to adres pierwszego wiersza tablicy dwywymiarowej. Czym to sie rozni od "a[0]"?

0

Nie! Wiersz to nie adres, Różnica jest kolosalna, np: http://ideone.com/1SQ1CP

#include <stdio.h>

int main()
  {
   int ROWS=7,COLS=5,a[ROWS][COLS];
   printf("%d\n",sizeof(a[0]));
   printf("%d\n",sizeof(&a[0]));
   return 0;
  }

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