• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Wskaźniki na wskaźniki

Object Storage Arubacloud
0 głosów
1,077 wizyt
pytanie zadane 22 lipca 2016 w C i C++ przez itcloud Gaduła (3,380 p.)

http://forum.pasja-informatyki.pl/100942/przekazywanie-tablicy-wskaznikow-dwuwymiarowej-do-funkcji
Może mi ktoś KROK po KROKU wyjaśnić na czym polega taki zapis jak niżej? Kiedy to stosujemy? Samo odczytanie, zinterpretowanie na głos linii nie jest dla mnie problemem: np. ** to "wskaźnik na wskaźnik". No i? Co z tego wynika? Nie mogę tego zrozumieć.

Np.

int **liczby = new int *[2];

albo

if(*(*(liczby+u)+k) < *(*(liczby+u)+k+1))
                    {
                        *wsk = *(liczby+k+1);
                        *(liczby+k+1) = *(liczby+k);
                        *(liczby+k) = *wsk;
                    }

O co tu kurcze chodzi? Samo pojęcie wskaźnika nie jest mi obce, wręcz załapałem o co chodzi od razu (nawiązanie do mapy pamięci, adresów, na które wskaźnik WSKAZUJE). Ale z takim kodem jak wyżej od strony interpretacyjnej po prostu "nie wyrabiam" :) Będę wdzięczny z pomoc.

4 odpowiedzi

+2 głosów
odpowiedź 22 lipca 2016 przez Sebastian Fojcik Nałogowiec (43,040 p.)

http://forum.pasja-informatyki.pl/158359/c-referencja-i-podwojne-gwiazdki

Tutaj dosyć wyczerpująco opisałem czym jest wskaźnik na wskaźnik, wraz z praktycznym przykładem użycia :-)

komentarz 22 lipca 2016 przez itcloud Gaduła (3,380 p.)
Chyba jednak nie do końca zrozumiałem, jeśli kod który tutaj wstawiłem nie jestem w stanie zrozumieć.

W tamtym poście zresztą pisałem jeszcze:

"Mozesz jeszcze na koniec napisać mi, czy te wskaźniki, rzutowanie wskażników, wskaźnik na wskaźnik.. to takie akademickie dysputy, temat do ogarnięcia pod kątem ew. testów na rozmowach rekrutacyjnych, czy w praktyce to się wykorzystuje?

Bo referencje jako argumenty funkcji czy wskażniki jako argumenty funkcji to na pewno i to "czuję", ale reszta to dla mnie czarna magia, nawet nie wiem jakie konkretne przykłady mógłbym testować, żeby sobie poćwiczyć.

Mój plan - owszem - jest taki, żeby powoli ale dokładnie opanować podstawy podstaw i dopiero zabierać sie za biblioteki, jakieś frameworki bo to myślę że opanuję, tym bardziej że mam doświadczenie z php i mysql-em. I widzisz, w web developerce znam konkretne przykłady: wiem, że interakcja z użytkownikiem opiera się na GET i POST poprzez formularze, wiem, jak zapisywać dane uzyskane od usera do bazy, jak je wyciągać, fetchować, jak używać regexpy itp, nawet coś na miarę szablonów sobie porobiłem, że o elementach obiektowości przy obsłudze bazy nie wspomnę. A przy c++ i tych podstawach, kompletnie nie mogę sobie wyobrazić jak te akademickie dysputy wykorzystać w praktyce :D"

widzę, że jednak wykorzystuje się wskażnik na wskaźnik (tutaj na forum, w praktycznych przykładach), ale nie do końca było to dla mnie jednak jasne.
komentarz 22 lipca 2016 przez Sebastian Fojcik Nałogowiec (43,040 p.)

Aaa wybacz, nie zauważyłem, że ten post napisała ta sama osoba. W takim przypadku nie linkowałbym tamtego postu XD

No więc rzutowanie wskaźników, które tam pokazywałem są bardziej ciekawostką niż czymś niezbędnym do pisania dobrego kodu. W 90% przypadków jeśli stosuje się wskaźnik na wskaźnik, to jest to kilkuwymiarowa tablica dynamiczna i kod, który tutaj wysłałeś właśnie to przedstawia. Jest to dwuwymiarowa tablica dynamiczna.

A ten if, który tam przestawiłeś jest przekombinowany i wygląda to tak, jakby osoba, która to pisała, nie chciała, aby ktokolwiek to zrozumiał. Weźmy prosty przykład z Twojego kodu:

*(liczby+k+1) = *(liczby+k);

No ludzie kochani, kto pisze takie rzeczy? Ani to dydaktyczne, ani ładne, ani praktyczne. Przecież powyższy kod powinien wyglądać tak:

liczby[ k+1 ] = liczby[ k ];

Przykład kodu, który podałeś, to jest jakaś składniowa porażka i wcale nie dziwię Ci się, że tego nie rozumiesz. Zamiast tego:

if(*(*(liczby+u)+k) < *(*(liczby+u)+k+1)) 

Powinno być:

if( liczby[ u ][ k ] < liczby[ u ][ k+1 ] )

Przyznasz, że czytelniej? Autor tego kodu najprawdopodobniej nigdy nie słyszał o operatorze [ ].

Nie polecam Ci czytania takiego kodu.
Nie zmienia to oczywiście faktu, że jako programista C++ powinieneś i taki kod umieć czytać. Właśnie jedną z wad stosowania wskaźników w swoich programach jest zmniejszona czytelność kodu. 
Ja przykładowo z kodu, który zamieściłeś potrafiłbym zrozumieć każdą linijkę z osobna, ale zrozumienie kodu jako całości (co robi jaka część), to już musiałbym posiedzieć... jak każdy :-)

Właśnie po to istnieje enkapsulacja. Programujesz z innymi osobami nie widząc kodu, który piszą. Nie musisz zawracać sobie tym głowy. Pozdrawiam :-)

0 głosów
odpowiedź 22 lipca 2016 przez Michał Muzyka Pasjonat (24,080 p.)
int **liczby = new int *[2]; 

dynamiczne stworzenie dwóch wskaźników

if(*(*(liczby+u)+k) < *(*(liczby+u)+k+1))
                    {
                        *wsk = *(liczby+k+1);
                        *(liczby+k+1) = *(liczby+k);
                        *(liczby+k) = *wsk;
                    } 

przeczesywanie dwuwymiarowej tablicy przy pomocy wskaźnika
tak jak normalnie przesuwasz:

int tablica[10];

for(int i=0; i<10; ++i)
   *(tablica + i) = i;   

//to jest to samo co:

for(int i=0; i<10; ++i)
  tablica[i] = i;   

tylko w twoim przykładzie dwuwymiarowa tablica, (podobno jest to szybsze ale nigdy z tego nie korzystałem)

 

komentarz 22 lipca 2016 przez itcloud Gaduła (3,380 p.)

>dynamiczne stworzenie dwóch wskaźników

No tak samo bym to przeczytał :) pisałem o tym, że czytać pojedyncze linie potrafię. Tylko dlaczego nie można zapisać:

int *liczby = new int [2];

albo

int *liczby = new int *[2];

Po prawej stronie new rozumiem, że dynamicznie jest tworzony wskaźnik na inta (a w zasadzie są to DWA ADRESY w pamięci wskazujące na jakieś dwie komórki trzymające inta... no ale w takim razie po co znowu wskaźnik na wskaźnik ??

komentarz 22 lipca 2016 przez Michał Muzyka Pasjonat (24,080 p.)

jak chcesz dynamicznie to zadeklarować to potrzebujesz wskaźnika na to, czyli

int    *liczby = new int    [2];

int   **liczby = new int   *[2];

int  ***liczby = new int  **[2];

int ****liczby = new int ***[2];

 

 

0 głosów
odpowiedź 22 lipca 2016 przez MichuDev Pasjonat (20,300 p.)

Zacznijmy od tego, że tablice w C/C++ są zamieniane na wskaźniki, ponieważ posiadają takie samo działanie więc zapis 

int ***tab;

może oznaczać trójwymiarową tablicę lub wskaźnik na wskaźnik na wskaźnik. Aby dobrze to zrozumieć trzeba wiedzieć to, że podczas zwiększania lub zmniejszania, lub odwołania się do niego jako n element tablicy uzyskujemy tak naprawdę wewnętrznie (jako wartość wskaźnika) wartość mniejszą (lub większą) o sizeof(typ tego na co wskazuje wskaźnik)*n które jest n-tym odwołaniem do elementu tablicy.

Wskaźnik na wskaźnik może być wskaźnikiem na wskaźnik lub tablicą wskaźników, co nie ma znaczenia ponieważ działanie jest takie same i można się do wskaźnika odwoływać jak do tablicy i odwrotnie. 

Prosto można powiedzieć, że procesor idzie tam gdzie wskaźnik, a potem robi to znowu i tak może być w przypadku wskaźnika na wskaźnik na wskaźnik... również.

komentarz 22 lipca 2016 przez itcloud Gaduła (3,380 p.)
Super, takiego wytłumaczenia potrzebowałem. Dzięki.
0 głosów
odpowiedź 24 lipca 2016 przez itcloud Gaduła (3,380 p.)

Jeszcze takie pytanie, bo uczę się równolegle Javy i C++ (a chcę konkretnie zaczać pisać w paktyce na Androida). W Javie z tego co wiem nie ma wskaźników. Jak tworzę jakąś klasę i potem odwołuję się do jej składowych czy metod to wygląda to mniej więcej tak, jak i w C++:

class Kotek{

int wielkosc;
String imie;

void miauczenie(){
  system.out.println("miau miau");
}

  public static void main (String[] args){
     Kotek kot1 = new Kotek();
     kot1.wielkosc = 10;
     kot1.miauczenie();
  }
}

no i jak to odnieść do wskaźników w c++? Tzn. w c++ często przy dynamicznej alokacji pamięci (operator new) przy zmiennej dodaje się znaczek * (wskaźnik), no bo chcę mieć jakby kotwicę do tego obszaru pamięci. Więc żeby mi się nie pokręciło, to co wyżej to po prostu tradycyjne odwołanie się do typowej zmiennej nazwanej, gdzie odnoszę się do elementów klasy (utworzonego obiektu) poprzez nazwę kopii obiektu, a nie w szybszy sposób czyli poprzez wskaźnik uzywany w c++ ?

 

Podobne pytania

0 głosów
2 odpowiedzi 225 wizyt
pytanie zadane 12 kwietnia 2022 w C i C++ przez xTMx3 Obywatel (1,560 p.)
0 głosów
1 odpowiedź 546 wizyt
pytanie zadane 26 października 2020 w C i C++ przez komboboost0 Użytkownik (570 p.)
0 głosów
0 odpowiedzi 429 wizyt

92,579 zapytań

141,429 odpowiedzi

319,655 komentarzy

61,962 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...