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

question-closed Co programista C++ powienien wiedzieć o wskaźnikach?

Object Storage Arubacloud
0 głosów
679 wizyt
pytanie zadane 15 stycznia 2018 w C i C++ przez Jakub 0 Pasjonat (23,120 p.)
zamknięte 17 stycznia 2018 przez Jakub 0

Witam, uczę się samemu C++, jestem na etapie wskaźników, przyznam że o ile same ich zastosowanie, użycie do konkretnych celów, współpraca ze strukturami... rozumiem, to mam problem z pojęciem bardziej złożonych np. takich przykładów arytmetyki wskaźnikowej:

To fragment mojego programu gdzie jakoś to wszystko ćwiczę, nauka tego idzie mi bardzo opornie (ciągle zapominam jak się tu dostać do jakiegoś adresu, robię głupie błędy, ciągle się gubię itd). Pytanie jest takie czy warto to wszystko umieć... Wolał bym zamiast tego jakiś projekt napisać frown. (bo ogólnie z C++ coś tam znam, nawet przy sfml grzebałem ale wróciłem do podstaw by zacząć naukę z książki [słyszałem że jest to lepsze źródło informacji] ). Wielu doświadczonych programistów mówi że dzisiaj wszystko zrobią za nas kontenery i takiego czegoś się rzadko używa ( podczas gdy sami idealnie to rozumieją (; ) Jaka jest prawda na ten temat? Dziękuje za rady i pozdrawiam

komentarz zamknięcia: Temat wyczerpany
komentarz 15 stycznia 2018 przez monika90 Pasjonat (22,940 p.)

*wsk2 + 2

Taka operacja jest w c++ niedozwolona. *wsk2 to wskaźnik do pojedynczego obiektu (tutaj wskazuje na zmienną x). Do takiego wskaźnika można dodać 0 albo 1, ale 2 już nie, bo to jest niezdefiniowane zachowanie.

komentarz 15 stycznia 2018 przez Jakub 0 Pasjonat (23,120 p.)
Znaczy wiedziałem że to jest błąd tylko zapomniałem dopisać notkę ;) ( bo tak ogólnie sprawdzam co jeśli...). Zaskoczyłem się tylko jedną rzeczą, dlaczego można dodać 0 lub 1?
1
komentarz 16 stycznia 2018 przez monika90 Pasjonat (22,940 p.)

W C i C++ używa się par wskaźników przy wykonywaniu operacji na części jakiejś tablicy. Używa się ich do zaznaczenia o który fragment tablicy chodzi. Jeden wskaźnik wskazuje na pierwszy element ciągu elementów, a drugi wskazuje nie na ostatni element, ale o jeden dalej. Np.:

int a[10] = {9,8,7,6,5,4,3,2,1,0};
std::sort(a + 1, a + 5);

posortuje elementy o indeksach 1,2,3,4. Żeby posortować całą tablicę a trzeba napisać:

std::sort(a, a + 10);

Tutaj a + 10 to wskaźnik poza zakresem tablicy, ale dopóki nie dokonasz dereferencji takiego wskaźnika to wszystko jest w porządku - można go używać do oznaczenia końca zakresu. Ogólnie dozwolone są wskaźniki które wskazują tuż za jakiś obiekt, ale jak wskazują trochę dalej za, albo tuż przed, to są błędne i powodują niezdefiniowane zachowanie. a + 11 albo a - 1 to już byłoby źle.

Wskaźnik do pojedynczego obiektu (który nie jest częścią tablicy) może być traktowany jak wskaźnik do pierwszego elementu jednoelementowej tablicy. Dlatego można do niego dodać jeden. Zero można dodać bo dodanie zera niczego nie zmienia.

Wiec na przykład taki dziwny kod jest poprawny choć nie robi niczego użytecznego:

int x = 42;
std::sort(&x, &x + 1);
komentarz 17 stycznia 2018 przez Jakub 0 Pasjonat (23,120 p.)
Dzięki za wytłumaczenie, ale w tym przypadku: *wsk2 + 2 , dopóki nie dokonam "dodatkowej" dereferencji nie będzie to chyba  powodowało żadnego nieokreślonego zachowania, bo teraz biorąc po uwagę wszelkie priorytety:

1. najpierw wyłuskanie więc wsk2 "zwraca" (wiem że niemiarodajne określenie) zawartość tablicy wskaźników o nazwie  'wsk1' o indeksie [0], tą zawartością jest jak na razie adres zmiennej 'x'

2. Potem dodajemy 2 czyli o ile dobrze rozumiem wskaźniki to: + 2*sizeof(int)

Teraz po prostu ten element tablicy wsk1 wskazuje na inny obiekt pamięci, ale samo to z punktu wiedzenia programu/kompilatora nie powoduje jeszcze błędu bo to tylko jakiś adres. Dopiero przy zapisie *(*wsk2 + 2) czyli wyłuskaniu wartości z pod tego adresu zaczną się problemy. Dobrze to rozumiem?
1
komentarz 17 stycznia 2018 przez monika90 Pasjonat (22,940 p.)
Tak to działa w przypadku kompilatora którego używasz. W innej implementacji C++ może być inaczej. Np. dodanie zbyt dużej liczby do wskaźnika spowoduje przepełnienie arytmetyczne, a przepełnienie spowoduje wyjątek sprzętowy i program zostanie przerwany.

Według Standardu C++ już samo dodanie dwójki to niezdefiniowane zachowanie. Niezdefiniowane zachowanie oznacza, że po programie można się spodziewać wszystkiego. Może się skompiluje, a może nie. Może się wykona bezbłędnie, a może nie. Może wyświetli na ekranie taki wynika jakiego się spodziewasz, a może coś zupełnie innego.
komentarz 17 stycznia 2018 przez Jakub 0 Pasjonat (23,120 p.)

Dzięki za pomoc i wyjaśnienie, i już mam nową wiedzę... wink Myślałem cały czas  że wskaźniki można ustawiać na obojętny adres a całe błędy mogą być tylko przy próbie odczytania wartości spod takiego adresu (dereferencji) gdzie nic sensownego nie ma, jednak widzę że wskaźniki są dużo bardziej groźne i mniej uniwersalne :/

1 odpowiedź

+1 głos
odpowiedź 15 stycznia 2018 przez Arkadiusz Sikorski Pasjonat (20,160 p.)

Rozsądny programista nie będzie tworzył tak zawiłych i skomplikowanych konstrukcji, jednakże warto nauczyć się je odczytywać i rozumieć (tak na wszelki wypadek). Jeśli chcesz nauczyć się czegoś naprawdę przydatnego to zainteresuj się wskaźnikami na funkcje (przykład zastosowania lub bardziej szczegółowo) oraz inteligentnymi wskaźnikami, np. unique_ptr.

 

PS. *(*(wsk2+2)) to mój faworyt, jeśli chodzi o brzydki kod laugh

komentarz 17 stycznia 2018 przez Jakub 0 Pasjonat (23,120 p.)
Poczekam aż dojdę do tego w książce, bo na razie uczę się wszystkiego co już wiem ;)

Podobne pytania

+1 głos
4 odpowiedzi 611 wizyt
+1 głos
5 odpowiedzi 734 wizyt
pytanie zadane 25 marca 2021 w C i C++ przez Whiskey_Taster Pasjonat (15,610 p.)
0 głosów
1 odpowiedź 383 wizyt
pytanie zadane 14 kwietnia 2016 w Offtop przez Shuhari Bywalec (2,060 p.)

92,624 zapytań

141,482 odpowiedzi

319,822 komentarzy

62,005 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!

...