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

Prośba o pomoc w zrozumieniu pętli

VPS Starter Arubacloud
0 głosów
692 wizyt
pytanie zadane 30 lipca 2016 w C i C++ przez Julenissen Początkujący (270 p.)

Cześć,  właśnie poznałem temat wskaźników. Piszę krótki program który zarezerwuje tyle int-ów w pamięci ile poda użytkownik. Utworzyłem wskaźnik tablica pod który zapisuję adresy tylu komórek tablicy ile zażyczy sobie użytkownik.

W materiałach od Pana Mirosława, aby zobaczyć kolejne adresy komórek zastosowana została pętla for (int i=0; i<ile; i++).

Zastanawia mnie jednak, skąd program wie którą komórkę wyświetlić. W cout mamy tylko "tablica" a nie np. "tablica [0]", dlaczego więc program zaczyna wyświetlać adresy od 0 komórki? Domyślam się, że ma to związek z inkrementacją poprzez "tablica++". Czy wpisując nazwę wskaźnika "tablica", program domyślnie umieszcza tam 0?

Będę wdzięczny za każdą odpowiedź. Pozdrawiam

 

int ile;

int main()
{
    cout<<"Ile liczb w tablicy: ";
    cin>>ile;

    int *tablica;
    tablica = new int;


    for (int i=0; i<ile; i++)
    {
        cout<<(int)tablica<<endl;
        tablica++;
    }
    return 0;
}

 

2 odpowiedzi

+2 głosów
odpowiedź 30 lipca 2016 przez Wi_ktos Bywalec (2,950 p.)
wybrane 30 lipca 2016 przez Julenissen
 
Najlepsza

Dzieje się tak ponieważ tablica jest wskaźnikiem inkrementacja wskaźnika, jak pewnie wiesz polega na przesunięciu o jeden dalej czyli tablica++; oznacza że chcemy aby wskaźnik pokazywał na kolejny utworzony obiekt;
POZDRO.wink
A i jeszcze taka sprawa że jeżeli chcesz aby to była tablica to musisz zmienić nieco definicje wskaźnika to znaczy jego przypisanie . W twoim wypadku powinno wyglądać to tak : tablica = new int[ile];. Dopiero wtedy tworzysz tablice jednowymiarową.

komentarz 30 lipca 2016 przez Julenissen Początkujący (270 p.)

Na wstępie dzięki za odpowiedź ;)

Miałbym jeszcze 2 pytania pomocnicze:

1. Pisząc "tablica jest wskaźnikiem" miałeś na myśli mój wskaźnik "tablica" czy generalnie wszystkie tablice? 

2. Na stronie http://www.algorytm.edu.pl/tablice-w-c/tablica-a-wskaznik.html znalazłem informację, że pierwszy (zerowy) wyraz z tablicy mogę wywołać poprzez:

cout<<"przykładowa_nazwa_tablicy"[0]        bądź

cout<< * "przykładowa_nazwa_tablicy"

Sprawdziłem, obie metody działają. Ale w kodzie mojego programu Pan Zelent zapisał cout<<tablica    zamiast    cout<< * tablica.  

Mimo to wyświetlanie adresów komórek rozpoczyna się od 0 komórki tablicy. Mógłbym Cię prosić o jakiś komentarz do sprawy?

PS. Dzięki, oczywiście powinno być tablica = new int[ile];  tak jak zapisałeś.

komentarz 31 lipca 2016 przez Wi_ktos Bywalec (2,950 p.)

1. Napisałem to odnośnie twojej sytuacji ( chodź generalnie nazwa tablicy jest wskaźnikiem do jej początku ) . Zdefiniowałeś tablice jako wskaźnik do obiektów typu int więc później tworzysz tablice , która jakby nie jest zdefiniowana ( powstaje w pamięci podręcznej ) a jedyny dostęp do niej masz za pomocą twojego wskaźnika. Obraz jest taki : tworzysz tablice, tylko na chwile więc nie definiujesz jej normalnie w pamięci komputera tylko w tak zwanej pamięci podręcznej i dostęp do niej masz tylko za pomocą wskaźnika , który ty nazwałeś tablica. teraz musisz uważać żeby przypadkiem nie ustawić twojego wskaźnika na inny obiekt bo stracisz dostęp do tej tablicy a co gorsza nie będziesz mógł jej z tej pamięci podręcznej usunąć.

2. Jak pisałem nazwa tablicy jaką zdeklarujesz jest też wskaźnikiem do jej początku , czyli zerowego elementu .

Jak coś jeszcze nie ok to pisz spróbuje jakoś czytelniej to wyjaśnić, polski nie jest moją dobrą stroną a tym bardziej składnia wypowiedzi wink.

komentarz 31 lipca 2016 przez Julenissen Początkujący (270 p.)

1. Wyjaśnione super - dzięki! :)

2. Kurczę tutaj mam mega problem. 

    for (int i=0; i<ile; i++)
    {
        cout<<(int)tablica<<endl;
        tablica++;
    }

Tak wyglada dzialajaca pętla Pana Zelenta. jednak nie wiem dlaczego ona działa skoro Pan Z. zapisał po prostu cout<<(int) tablica zamiast cout<<(int)*tablica. W razie jakbyś nie zauważył o co mi chodzi napiszę: Gdzie się podział symbol * używany przy wskaźnikach?! laugh Tak jak pisałem pierwszy (zerowy) wyraz z tablicy mogę wywołać w moim przykładzie poprzez

cout<<tablica[0]        bądź      cout<<*​tablica

Ale nie powinno się móc go wywoyłać pisząc cout<<tablica. Więc jakim cudem ta pętla działa? laugh

PS. Wiem oczywiście, że dopisek (int) przed wskaznikiem służy do konwersji wyswietlanych adresów z szesnastkowego na dziesietny sposob zapisu.

PS 2. Na koniec już totalny mindfuck. Wpisałem niżej, już poza pętlą linję kodu

cout<<endl<<(int)*tablica<<endl<<(int)tablica[0];

Dwa adresy zerowej komórki tablicy wyświetliły się poprawnie, oba takie same. Jednak nie zgadzają się one z pierwszym adresem wyświetlanym poprzez pętlę, który przecież powinien być taki sam ponieważ jest adresem zerowej komórki tablicy.

Proszę pomóż mi, bo głowa zaczyna powoli parować wink

komentarz 31 lipca 2016 przez Wi_ktos Bywalec (2,950 p.)

Kompletnie zgubiłeś ideę wskaźników. Zapis jeżeli odnosimy się do wskaźnika bez gwiazdki to chodzi nam o jego adres. Zauważ, że jak ustawiasz wskaźnik na jakiś obiekt to piszesz :
int i;
int *wskaznik_do_i;
wskaznik_do_i = i;
To znaczy chcesz aby wskaźnik pokazywał na komórkę o tym adresie.
Jeśli natomiast odnosisz się do wskaźnika używając gwiazdki to tak jakbyś odnosił się do obiektu na który ten wskaźnik pokazuje. Z początku wydawać by się mogło ,że jest to sztuka dla sztuki ale uwierz ,że później dowiesz się czemu są tak ważne.
Ten program , to znaczy ta konkretna pętla o która pytasz wypisuje tylko adresy tych komórek w pamięci w systemie dziesiątkowym.
Swoją drogą ten sposób tj. (int)tablica jest stary. Aktualnie używa się operatora reinterpret_cast<int>(tablica); i tak to powinno wyglądać ale jeśli dopiero zaczynasz programować to wersja (int)tablica; jest jak najbardziej poprawna. To tak na marginesie smiley.
Mam nadzieje ,że wszystko już jasne jeśli chodzi o mechanikę wskaźników i ich ideę :).
Jak coś pytaj śmiało pozdrawiam.  

komentarz 1 sierpnia 2016 przez Julenissen Początkujący (270 p.)

Haha, dzięki jesteś wielki! Faktycznie trochę się zagubiłem :) Zastanawia mnie jeszcze jedna rzecz. Jeżeli spojrzysz na cały kod który wkleję poniżej, zauważysz, że nigdzie nie deklarowałem żadnej wartości pod pierwszą komórką tablicy. Natomiast z linijek cout<<*tablica<<tablica[0] czyli takich które odnoszą się do obiektu na który ten wskaźnik pokazuje, wychodzą 2 wartości, różne za każdym razem. Na screenshot'cie jest pokazany obraz z programu, na zapytanie "Ile liczb w tablicy" odpowiedziałem 5, stąd też  5 adresów (one też są różne, za każdym razem gdy odpalam program - ale to oczywiście normalne i zrozumiałe). Chodzi mi jednak o te 2 linijki niżej. Mam nadzieję, że udało mi się przekazać sens moich rozważań ;)

int ile;

int main()
{
    cout<<"Ile liczb w tablicy: ";
    cin>>ile;

    int *tablica;
    tablica = new int [ile];


    for (int i=0; i<=ile; i++)
    {
        cout<<(int)tablica<<endl;
        tablica++;
    }

    cout<<endl<<(int)*tablica<<endl<<(int)tablica[0];
    return 0;
}

komentarz 1 sierpnia 2016 przez Wi_ktos Bywalec (2,950 p.)

Po pierwsze usuń to (int)*tablica bo to głupota troszkę i niepotrzebna rzecz zupełnie smiley, ponieważ pokazuje to na komórkę w której jest "śmieć", a ty go tłumaczysz na int .To nie ma sensu troszkę w tym wypadku. W swojej pętli dodaj taką linijkę przed tablica++:
*tablica = i;
wtedy przypiszesz tym obiektom aktualną wartości i, wypełniając tym samym swoją tablicę ( utworzoną ) kolejnymi liczbami całkowitymi.  
Co do problemu to nie wiem czy dobrze zrozumiałem ale pytasz czemu za każdym razem kiedy kompilujesz obiekty na które pokazują wskaźniki są różne? Jeśli tak to jest tak dlatego ,że za każdym razem kiedy wykonujesz kompilacje program rezerwuje nowe miejsca w pamięci i nie muszą być one te same (adresy z kompilacją też się zmieniają) , więc "śmieci", które tkwią w tych komórkach pamięci są za każdym razem inne (losowe).   

komentarz 1 sierpnia 2016 przez Julenissen Początkujący (270 p.)

"Po pierwsze usuń to (int)*tablica bo to głupota troszkę i niepotrzebna rzecz zupełnie smiley, ponieważ pokazuje to na komórkę w której jest "śmieć", a ty go tłumaczysz na int ."

Chodzi mi o to skąd się bierze ten "śmieć" wink Rozumiem, że w tych pięciu linijkach jest 5 różnych adresów, o to chodzi w pisanym przeze mnie programie. Ale na jakiej podstawie program bierze sobie tego "śmiecia"?

komentarz 1 sierpnia 2016 przez Wi_ktos Bywalec (2,950 p.)
On tam po prostu jest. W każdej komórce jest "coś" i do póki tego nie zainicjujesz ten "śmieć" tam będziesz. Chyba ,że zadeklarujesz obiekt globalny lub statyczne one od razu inicjowane są zerami.
komentarz 1 sierpnia 2016 przez Julenissen Początkujący (270 p.)

OK, jeszcze raz bardzo, bardzo dziękuję Ci za pomoc! smiley Jestem nowy na forum, jeśli mogę się jakoś odwdzięczyć to daj znać!

komentarz 1 sierpnia 2016 przez Wi_ktos Bywalec (2,950 p.)

Nie ma za co wink

+1 głos
odpowiedź 30 lipca 2016 przez mbabane Szeryf (79,280 p.)
http://www.algorytm.edu.pl/tablice-w-c/tablica-a-wskaznik.html

I ogolnie Twoje zalozenie w tym kodzie jest niespelnione.
komentarz 30 lipca 2016 przez Julenissen Początkujący (270 p.)
Dziękuję Ci bardzo za odpowiedź :) Strona którą mi podesłałeś jest super.

Podobne pytania

0 głosów
1 odpowiedź 763 wizyt
0 głosów
1 odpowiedź 162 wizyt
pytanie zadane 16 marca 2019 w C i C++ przez Mavannkas Bywalec (2,290 p.)

92,454 zapytań

141,262 odpowiedzi

319,089 komentarzy

61,854 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

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 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!

...