Skomplikowany zapis deklaracji wskaźników

0

Otóż mam taki problem, że zaczynam dopiero wskaźniki i nie rozumiem takiego oto kodu i prosiłbym o wytłumaczenie kilku zaznaczonych linijek:)

    int rozmiar;
    cout << "Podaj rozmiar tablicy: ";
    cin >> rozmiar;

    int *tablica;      // tutaj deklarujemy wskaznik wskazujacy typ int o nazwie tablica (jasne) //
    tablica = new int [rozmiar];  // a tutaj jest kosmos, nagle z jednego wskaźnika robi sie ich tablica, jak??:/ //

    for (int i=0; i<=rozmiar; i++)
    {
        cout << tablica << endl;  
        tablica++;       
    }
    delete [] tablica;

No i jeszcze pętla:
Przy cout'cie zawartosci wskaznika nie ma okreslonych komorek [] tablicy, np od tablica[0] lecimy do zad rozmiaru do np tablica[x], no i stąd nie wiem skąd zaczynamy.
I linia nizej z inkrementacją, i tu problem z linijki wyzej, nie ma [] wiec jak zwiekszamy komorke tablicy?? #mind fck //

2

Tak działa arytmetyka wskaźników - mając adres zmiennej w pamięci równie dobrze może być to pierwszy element tablicy jak i po prostu jedna zmienna.

Tak zostało to rozwiązane w C i tak zostało zaimportowane do C++.

mając taki wskaźnik, wiedz o kilku rzeczach:

  • tablica+1 doda do wskaźnika długość jednego elementu (nie bajtu!), więc będzie wskazywać na następny element tablicy (o ile to jest rzeczywiście tablica)
  • *tablica to dereferencja
  • tablica[n] to to samo co *(tablica+n)

BTW: https://dsp.krzaq.cc/post/176/ucze-sie-cxx-kiedy-uzywac-new-i-delete/

0

Czyli jesli dobrze rozumiem, mozemy "inkrementowac" zmienna o nazwie tablica?, bo ona jest takze adresem pierwszej komorki tablicy? i "zwiekszając" zmienna dostajemy sie danej komorki?
Edit: Ale nadal chyba nie wiem jak z jednej zmiennej ze wskaznikiem powstala ich cala tablica..

0

Zwiększając ją (a właściwie wykonując na niej operacje arytmetyczne) poruszasz się po tablicy.

Nie wiem czy podpasuje Ci ta analogia, ale wskaźnik to taki nr. domu na ulicy. Dodasz 1 to masz następny, odejmiesz to masz poprzedni, a żeby zobaczyć co jest w środku musisz wejść za pomocą *.

0

wskaźnik to taki nr. domu na ulicy.

Dodałbym chyba, ze do domow sa przyczepione skrzynki, a w ich srodku jest nr domu xd, Ale to moje wyobrażenie:d
A co do poprzedniej Twojej odpowiedzi to wlasnie co by bylo gdybym dodal do zmiennej ze wskaznikiem +1 a to nie bylaby tablica?

0

To miałbyś tzw. UB, czyli niezdefiniowane zachowanie. Nie da się rzetelnie powiedzieć co się wtedy stanie, bo język tego nie definiuje. Ty, jako programista, masz do tego po prostu nie dopuścić.

To samo dotyczy np. wyjścia więcej niż 1 element poza koniec tablicy, lub próba dereferencji obiektu poza końcami tablicy.

Co do skrzynek to nie rozumiem za bardzo. Rozwijając analogię:

// PSEUDOKOD
Dom* krakowskie_przedmieście = 48; // pałac prezydencki, krakowskie przedmieście 48
krakowskie_przedmieście + 10; // adres krakowskie przedmieście 58
*krakowskie_przedmieście; // dereferencja, w tej analogii wchodzisz do pałacu prezydenckiego
krakowskie_przedmieście[0]; // to samo
krakowskie_przedmieście[10]; // wchodzisz do budynku pod adresem krakowskie przedmieście 58
0

Pomyslalem ze moze moglibysmy zmienic adres wskaznika o 1 bit:d

0

Co do skrzynek to nie rozumiem za bardzo.

Jesli chcesz zrozumieć jak ja mysle:):
Istnieje dom.
Istnieje jego adres w skrzynce, ale nwm jak ja otworzyc.
Tworze wskaznik z nazwą domu zeby moc otworzyc skrzynke i dostac sie do jego adresu-nr domu:d

0

Nie, dostajesz się do zawartości, nie do adresu.

Może zamiast domów numerowane skrytki np. jak są na dworcach.

Numer skrytki to jej adres. Co jest w środku to zawartość. Adres możesz zwiększać/zmniejszać i będzie on wskazywał na różne skrytki. Po dereferencji uzyskasz zawartość skrytki.

0

No tak, ale uzywając nazwy wskażnika, odczytujemy adres, a uzywając operatora wskaźnika dostajemy sie do środka. Te analogie są do bani, cięzko to porównac, moje zdanie. Widzisz ja myslalem wcześniej o tym pierwszym dostaniu sie do skrzynki, a Ty do zawartości zmiennej, DAmn, cięzko użyc jednej analogii. Anyway dzięki za poświęcony czas, wracam do nauki.

1

Bracie @Spark_of_hope traktuj może wskaźnik jako taki skrót do jakiejś danej w pamięci. Skrót ów możesz sobie nastawiać na dowolny typ dla którego go zdefiniowałeś, czyli jak na int to możesz odnosić się do int-ów, albo tablic intów. Jeśli używasz owego skrótu bez * to zmieniasz wskazanie na co pokazuje wskaźnik - te wszystkie +1, -1 co ci kq demonstrował.
Jeżeli chcesz sięgnąć "do wnętrza" wskaźnika aby zrobić coś z daną, na którą on wskazuje to wtedy używasz *.
Ot i cała filozofia.

Taka jeszcze dygresja odnośnie dynamicznych tablic:

    int *tablica;      // tutaj deklarujemy wskaznik wskazujacy typ int o nazwie tablica (jasne) //
    tablica = new int [rozmiar];  // a tutaj jest kosmos, nagle z jednego wskaźnika robi sie ich tablica, jak??:/ //

Magia polega na tym, że int *tablica umie wskazywać na element typu int, natomiast new int[ileśtam] powoduje, że pamięci tworzy się taka struktura leżących zaraz obok siebie intów:
| int1 | int2 | int3 | .... | int ileśtam |
i teraz *tablica wskazuje na int1. Ponieważ za 1 intem jest drugi to jak do tablica dodasz 1 co w języku C/C++ oznacza "przesuń wskaźnik *tablica o 1 wielkość elementu dla którego zostałaś zdefiniowana" spowoduje to, że teraz w *tablica będzie adres inta2. I tak aż do inta ileśtam.

Cyrk zacznie się dziać jak po przesunięciu *tablicy na inta ileśtam znów dodasz jeden lub więcej, albo kiedy *tablica wskazuje na inta1 a ty odejmiesz od niej 1 lub więcej.

W takim wypadku nie wiadomo, co znajduje się przed oraz za dynamicznie stworzoną tablicą, i czy masz dostęp do tej pamięci. Stąd sytuacja ta jest oznaczana jako Undefined Behavior.

Jeszcze jedna uwaga - jak tworzysz sobie dynamicznie tablicę to lepiej nie zmieniać wskaźnika który wskazuje na jej początek, bo nietrudno potem "zapomnieć" w programie gdzie się ona znajduje. Dlatego *tablicę w przykładowym programie lepiej zapisać tak:

int *const tablica = new int [rozmiar];

to gwarantuje, że nie przestawisz sobie przypadkiem wskaźnika *tablica na coś innego niż początek dynamicznej tablicy.

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