Programowanie w języku C, wskaźniki.

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.

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.

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.

6

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

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:

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

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

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.

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