←  Tutoriale

AMXX.pl: Support AMX Mod X i SourceMod

»

C++
Wskaźniki

Zablokowany

  • +
  • -
DarkGL - zdjęcie DarkGL 22.06.2010

Wskaźnik to obiekt przechowujący adres innego obiektu.
Prosty przykład:
int main(){
           int liczba = 7;
           std::cout<<"Adres liczba"<<&liczba<<std::endl;
           int* wsk = &liczba  // zmienna wsk przechowuje adres liczba
           std::cout<<"Pod adresem"<<wsk<<"jest liczba"<<*wsk<<std::endl;
           *wsk = 15;
           std::cout <<"Teraz liczba = "<<liczba<<std::endl;
}
do odczytania adresów zmiennych służy operator &.
wyjaśnijmy linijkę
int* wsk = &x  // zmienna wsk przechowuje adres liczba
tutaj na lewo od gwiazdki znajduje się identyfikator typu int , dlatego zmienna wsk może przechowywać adresy liczb typu int. Typem zmiennej wsk jest int*
Skoro mamy wskaźnik możemy na niej wykonać dwie rzeczy.
1.uzyskać wartość obiektu na którą wskazuje wskaźnik służy do tego operator *
2.zmienienie jej wartości kod:

int x = 0 , y =2;
int* wsk = &x;
p = &y

Wskaźniki stałe to wskaźniki które zawsze mają te samą wartość (zawsze wskazują ten sam obiekt) wskaźniki stałem muszą być zainicjowane adresem obiektu od razu przy tworzeniu.
int x =0;
int* const wsk = &x; // wsk jest stalym wskaźnikiem na x
Wskaźniki na stałą to wskaźniki umożliwiające jedynie odczytanie stanu obiektu
int x =0;
const int* wsk = &x; // wsk jest wskaźnikiem na stałą
i dodatkowo można utworzyć stały wskaźnik na stałą ;)
int x = 0;
const int* const wsk = &x;

Wskaźniki na wskaźniki
int x = 0;
int* wsk = &x;
int** wsk2 = &wsk;

Void*
jest to specjalny typ wskaźników który charakteryzuje się tym że można przypisać mu wartość wskaźnika dowolnego typu

int x = 0;
int* wsk = &x; // wsk wskazuje na x
void* wsk2 = wsk; //w wsk2 jest wartość wsk czyli adres x

taki kod służy w C do przekazywania do funkcji argumentów dowolnego typu nie jest to zbyt ładne prawda ?
dlatego w swoim kodzie nigdy nie używaj void* w c++ slużą do tego szablony

Wskaźnik zerowy
jest to wskaźnik o wartości 0 oznacza to że nie wskazuje on na żaden obiekt można też używać NULL

Tablice a wskaźniki

jeżeli wykonamy taki kod
int tab[2] = {0};
std::cout<<tab<<std::endl;
std::cout<<&tab[0]<<std::endl;

dostaniemy ten sam adres

więc możemy powiedzieć że nazwa tablicy może być traktowana jak wskaźnik na jej pierwszy element

dalej
int tab[2] = {0,1};
int* wsk = tab;
std::cout<<wsk<<std::endl;
std::cout<<*wsk<<std::endl;
std::cout<<wsk[1]<<std::endl;
po koleji
w pierwszej linijce dostaniemy ten sam adres jaki byśmy zobaczyli gdybyśmy przesłali tab
w następnej zobaczymy 0 czyli wartość pierwszego elementu
a w następnej wartość drugiego elementu czyli 1;)
czyli podsumowując
Wskaźników można używać jak nazw tablic , a nazw tablic jak wskaźników :ganja:
Użytkownik DarkGL edytował ten post 03.08.2010 16:05
Odpowiedz

-PainKiller- - zdjęcie -PainKiller- 22.06.2010

nigdy tego nierozkminama m i teraz tez nie ale mnoze rano sprobuje bo teraz jestem w stanie niewazkosci alkoholowej
pozdrawiam
ogolnie nie wiem do czegostuo suje sie wskazniki
Odpowiedz

  • +
  • -
R3X - zdjęcie R3X 22.06.2010

Trochę zabrakło prezycji, bo wskaźniki to nie obiekty :P w C90 są wskaźniki, a nie jest obiektowe.

Wskaźniki (i referencje) służą do lekkiego przekazywania parametrów do funkcji, np dlatego tablice zawsze są przekazywane przez wskaźnik.
int [] tab jest tym samym co int *tab;
Odpowiedz

  • +
  • -
DarkGL - zdjęcie DarkGL 22.06.2010

warto dodać że w c nie ma referencji więc wskaźniki to podstawa chociaż w programach pisanych w c++ nie warto ich używać ;)
C90 :D?
Użytkownik DarkGL edytował ten post 22.06.2010 22:06
Odpowiedz

  • +
  • -
R3X - zdjęcie R3X 22.06.2010

Brakuje mi tu praktycznych przykładów ;)

PS. chodziło mi raczej o standard C z roku 1990, ale wyrzutnia jest ok też
Odpowiedz

  • +
  • -
G[o]Q - zdjęcie G[o]Q 23.06.2010

hmm mozesz opisac tez wskazniki do funkcji i ich przekazywanie do innej funkcji (jak cos to ci moge materialy podeslac) bo to jest o tyle ciekawa rzecz ze mozna zrobic cos jak w pawnie funkcje majace obslugiwac sortowanie :D
Odpowiedz

  • +
  • -
DarkGL - zdjęcie DarkGL 23.06.2010

dodałem co miałem dodać :D
Odpowiedz

  • +
  • -
Owner123 - zdjęcie Owner123 28.07.2010

Mała poprawka - nie ma wskaźnika zerowego, są jedynie wskaźniki ustawione na adres zerowy. ;)
Odpowiedz

-PainKiller- - zdjęcie -PainKiller- 24.10.2010

przeczytałem twoją teorię i szczerze mówiąc ciężko się połapać, jako że ostatnio intensywnie działam w c++ to napiszę to po swojemu może komuś będzie łatwiej zrozumieć...

musimy uruchomić wyobraźnię i zejść nieco niżej niż c++...

Na początek musimy zrozumieć istotną rzecz w programowaniu, jak wiadomo niektóre języki wymagają kompilatorów, niektóre nie. C++ nie jest językiem niskopoziomowym dlatego musi być kompilowany na poziom niższy, maszynowy lub binarny, jak zwał tak zwał chodzi o to że procesor sam z siebie nie rozumie języka c++ dlatego musi go dostać w postaci binarnej (0101010101) do tego służy kompilator który jakby przekonwertuje nasz kod c++ na kod maszynowy - zrozumiały dla procesora.

Gdy procesor ma już kod, który rozumie to w zależności od programu (właściwie tylko prymitywny program nie spełni tego warunku) tworzy sobie ileś tam obiektów, zmiennych. Każda definicja zmiennej jest jakby poleceniem, podam dla przykładu...
int x;
klepiąc taki kod dajemy procesorowi polecenie: "zarezerwuj w pamięci mi na przyszłość miejsce pod kryptonimem x, w którym później będę mógł trzymać dane w postaci liczb całkowitych"

co sie dzieje?
procesor wysyła cynka do pamięci że chce owy typ danych zarezerwować, oczywiście można zagłębiać sie w szczegóły ile zajmie to komórek (mówimy o RAMIE) w kości i tak dalej.. ale chodzi o to że teraz możemy w pamięci mieć te dane i jakoś się do nich odwołać, czy to wywołać czy wprowadzić...

sposobów jest wiele ale na ten temat wystarczą:
- przez nazwe zmiennej
- przez utworzony wskaźnik

mała anegdota jaka podaje Grębosz w symfoni c++ (zmienie tresc, sens ten sam)
robisz zadanie z angielskiego i korzystasz z słownika który ma 1000 stron, załóżmy że szukasz słowa "wskaźnik" jest ono na 820 stronie jednak nie masz spisu treści, masz tylko ułożone wg alfabetu więc jedziesz po kolei kartka za kartką aż udaje ci sie dojść do owej strony, odczytujesz jak jest po angielsku i zamykasz słownik. Niestety w tym czasie mama weszła do pokoju i mowi ci wyłacz komputer a ty nie chcesz tego zrobic, ona wyszla a ty w tym czasie zapomniales jak "wskaźnik" było po angielsku.... no to jedziesz od nowa znowu kartka za kartką (zakładamy że masz IQ = 0 i nie wiesz nawet mniej więcej że jest to w drugiej czesci slownika, bo komputer jak wiadomo nie ma inteligencji wiec on to bedzie tak robil....) i nagle ci sie udało, znowu wiesz jak jest "wskaźnik" po angielsku ale teraz wszedł to pokoju tata i zaczyna ci nawijać żebyś mu umył auto, tym razem sie wycwaniłeś i zapisujesz sobie obok na kartce na której stronie masz tłumaczenie słowa wskaźnik....

Teraz już chyba znasz istote wskaźników- chodzi o szybszy dostęp do komórek pamięci gdzie zapisane są dane(wskaźnik wskazuje na adres w pamieci RAM gdzie jest owa zmienna, obiekt)

wskaźnik musi być tego samego typu co zmienna wskazywana a więc

#include <iostream>

using namespace std;

main(){

int zmienna=8, drugi = 4;   //załózmy ze pod nazwa "zmienna" jest owe słowo "wskaźnik"(ze słownika) a pod nazwa "drugi" jest hasło "pamięć" też ze słownika czyli ma ono inną strone w słowniku (w przypadku wskaźników ma inny adres komórek w RAM)
int *wskaznik;     //tworznie wskaźnika typu int 

wskaznik = &zmienna;    //ustawienie wskaźnika na zmienną, zmienna o nazwie "drugi" nie posiada w tym momencie wskaźnika, nie wiesz gdzie w słowniku jest słowo "pamięć"

cout<<"zmienna odczytana przez nazwe zmiennej: "<<zmienna<<"a odczytana przez wskaznik"<<*wskaznik<<endl; 

zmienna = 100; // ZMIENIAMY WARTOŚĆ ZMIENNEJ nie odwołujac sie przez wskaznik ale przez jej nazwe

cout<<"zmienna odczytana przez nazwe zmiennej: "<<zmienna<<"a odczytana przez wskaznik"<<*wskaznik<<endl;

*wskaznik = 200; //zmieniamy wartość zmiennej "zmienna" ale nie przez jej nazwe a przez wskaźnik, wskaźnik caly czas jest ustawiony na zmienną "zmienna" 
cout<<"zmienna odczytana przez nazwe zmiennej: "<<zmienna<<"a odczytana przez wskaznik"<<*wskaznik<<endl; 

wskaznik = &drugi; //ZMIENIAMY OBIEKT NA KTÓRY WSKAZYWAŁ BĘDZIE WSKAŹNIK czyli jakby skreślamy z naszej kartki strone słowa "wskaźnik" a zapisujemy strone na której jest tłumaczenie słowa "pamięć" 

cout<<"zmienna odczytana przez nazwe zmiennej: "<<zmienna<<"a odczytana przez wskaznik"<<*wskaznik<<endl; 
}

Ogólnie bez wskaźników da sie życ, są one przydatne w naprawdę wielkich projektach, jak na dzisiejsze pamieci RAM można napisać sporo wieloplikowych aplikacji z konkretna zawartoscia kodu bez wskaźników bez utraty szybkości ale gdy ktos sie programowaniem bardziej interesuje to chyba powinien to wiedzieć.


większość napisałęm od siebie, ja tak rozumiem wskaźniki jeśli coś źle ujałem a jest tu ktoś kto wie lepiej to czekam na korekty....
Odpowiedz

  • +
  • -
G[o]Q - zdjęcie G[o]Q 25.10.2010

w symfonii bylo o pociagach :D i szczerze mowiac to gdybym nie znal c++ to twojego textu bym nie zrozumial bo wskaznik tylko pokazuje na dany adres w pamieci wiec mozemy sie dostac do danego obszaru kiedy chcemy :D
Odpowiedz

-PainKiller- - zdjęcie -PainKiller- 25.10.2010

szczerze mowiac to gdybym nie znal c++ to twojego textu bym nie zrozumial

raczej nikt by nie zrozumiał bo nikt o zdrowym umyśle nie zacznie nauki c++ od wskaźników... :rolleyes:
Odpowiedz

MaDaFaKa - zdjęcie MaDaFaKa 17.11.2010

Ładny poradnik. Niestety jest jedno "ale". Gdybym nie znał c++ to bym niestety nic z tego nie zrozumiał :/
Odpowiedz

  • +
  • -
DarkGL - zdjęcie DarkGL 17.11.2010

jak to już ktoś napisał nie zaczyna się nauki c++ od wskaźników ;D
Odpowiedz

MaDaFaKa - zdjęcie MaDaFaKa 17.11.2010

Wiem o tym, bo jest to sprawa, że tak powiem "bardziej zaawansowana". Moim zdaniem poradniki powinny być zrozumiałe dla wszystkich, nawet początkujących, dlatego ująłem to w tamtym poście.
Odpowiedz

  • +
  • -
mgr inż. Pavulon - zdjęcie mgr inż. Pavulon 18.11.2010

Moim zdaniem poradniki powinny być zrozumiałe dla wszystkich, nawet początkujących, dlatego ująłem to w tamtym poście.

ale każdy poradnik musi wymagać jakiejś wiedzy w danej dziedzinie...
nie da się uczyć programowania od stopnia zaawansowanego, to tak jakby uczyć się całkowania, różniczkowania czy liczb zespolonych bez znajomości funkcji trygonometrycznych o_O
Odpowiedz
Zablokowany