Programowanie w języku C, wskaźniki.

Programowanie w języku C, wskaźniki.
Samhain
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 15
0

Cześć, chcę zapytać o wskaźniki. Wiem jak się je tworzy, znam ich ogóle założenia jednak nie bardzo wiem, kiedy dokładnie należy ich użyć? Po co ich w ogóle używać? Może mi ktoś to wyjaśnić? Nie bardzo mogę zrozumieć funkcję, jaką pełnią wskaźniki w programowaniu.

stivens
  • Rejestracja: dni
  • Ostatnio: dni
2

Jak masz np. tablice 2-megabajtowa to nie bedziesz wszystkiego kopiowal tylko w argumencie podasz jej adres.

Jak chcesz zmodyfikowac cos zeby na zewnatrz to bylo widoczne no to bez wskaznika tez moze byc ciezko.

No i czesto jest tak, ze to co pod wskaznikiem to zyje na stercie a nie stosie.

PerlMonk
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Warszawa 🐪
  • Postów: 1719
1

To, co napisał @stivens to kwestia optymalizacji. Wskaźniki są po to, żeby programista decydował jak korzystać z pamięci. Przykładem jest odczytywanie plików wave. Są to duże pliki, więc:

  • kopiowanie ich między funkcjami zajmowałoby dużo czasu,
  • w momencie pisania kodu nie wiemy ile bitów ma próbka, więc musimy odczytać do z nagłówka i odpowiednio potraktować dane - zrobić brzydką konwersję z void* na typ np. short* albo char*.

W nowszych standardach C++ nie ma potrzeby pisania typów z gwiazdką, bo są od tego klasy. Dlatego w C++ kiedyś może zabraknąć jawnej deklaracji wskaźników na rzecz klas w stylu unique_ptr.

elwis
  • Rejestracja: dni
  • Ostatnio: dni
6

Są 4 podstawowe przyczyny dla używania wskaźników. Po pierwsze, kiedy chcemy zmienić wartość poza funkcją. Jeśli masz funkcję:

Kopiuj
int foo(int x) {
   x+=4;
   return x;
}

To wywołując funkcję: foo(z) to wartość zmiennej z się nie zmieni. Jesli chcemy coś zmienić nazewnątrz funkcji, musimy użyć wskaźnika. Nie jest to szczególnie dobra praktyka, ale często, ze względów wydajnościowych tak się robi. W szczególności gdy mamy funkcję, która wypełnia jakąś strukturę, to zaalokowanie pamięci jest po stronie wywołującego, a funkcja tylko zapisuje wartości. Weźmy na przykład wywołanie:

Kopiuj
int x;
scanf("%d", &x);

Żeby ustawić wartość x, scanf musi dostać wskaźnik. inny przykład z POSIXowego API:

Kopiuj
struct stat sb;
if(stat(argv[i], &sb) == -1) {
   printf("nie mozna sprawdzić pliku %s\n", argv[i]);
   exit(1);
}

Teoretycznie funkcja stat mogłaby zwrócić wartość typu stat sb i w nowoczesnym C, nawet byłoby to wydajne. Jednak w czasach gdy to API było tworzone nie koniecznie. Bez optymalizacji, ten sam obszar pamięci byłby zaalokowany 2 razy (w funkcji stat i poza nią) i raz skopiowany z jednego do drugiego. Natomiast alokowanie dynamiczne wewnątrz byłoby mniej wydajne i podatne na błędy. Dlatego stosuje się zwracanie wartości przez wskaźnik. Przy okazji, dzięki temu można zwrócić dwie wartości na raz, bo funkcja sama w sobie zwraca kod błedu, po którym określamy czy funkcja się powiodła.

Po drugie, czasem, jak @stivens pisze, chcemy odnieść się do kawałka pamięci bez kopiowania go. W szczególności, bez wskaźników nie dałoby się zaimplementować listy (podobnie z drzewami), bo jej istotą jest to, że każdy element jest odrębnym kawałkiem pamięci i wszystkie są tylko powiązane wskaźnikami.

Po trzecie, tablice to w gruncie rzeczy wskaźniki do większych kawałków pamięci.

Wreszcie po czwarte, Każda zmienna ma swoje miejsce w pamięci. Gdy alokujemy na stosie (zmienne lokalne) czy w sekcji danych (zmienne globalne) adres jest znany już w czasie linkowania. Jednak nie zawsze one wystarczą. Często musimy alokować pamięć dynamicznie (funkcja malloc()). Wówczas nie ma innego sposobu, żeby odnieść się do zawartości pamięci, jak tylko przez wskaźnik.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.