C++ Wskaźniki z przykładami
Czym są wskaźniki?
In C++, wskaźnik odnosi się do zmiennej, która przechowuje adres innej zmiennej. Podobnie jak zwykłe zmienne, wskaźniki mają typ danych. Na przykład wskaźnik typu integer może przechowywać adres zmiennej typu integer. Wskaźnik typu znakowego może przechowywać adres zmiennej typu znakowego.
Powinieneś zobaczyć wskaźnik jako symboliczną reprezentację adresu pamięci. Za pomocą wskaźników programy mogą symulować wywołanie przez odwołanie. Mogą także tworzyć i manipulować dynamicznymi strukturami danych. W C++, zmienna wskaźnikowa odnosi się do zmiennej wskazującej konkretny adres w pamięci wskazywany przez inną zmienną.
Adresy w C++
Rozumieć C++ wskaźników, musisz zrozumieć, w jaki sposób komputery przechowują dane.
Kiedy tworzysz zmienną w pliku C++ programu, przydzielana jest mu część pamięci komputera. Wartość tej zmiennej przechowywana jest w przypisanej lokalizacji.
Aby poznać miejsce w pamięci komputera, w którym przechowywane są dane, C++ zapewnia & (odniesienie) operator. Operator zwraca adres, który zajmuje zmienna.
Na przykład, jeśli x jest zmienną, &x zwraca adres zmiennej.
Składnia deklaracji wskaźnika
Deklaracja C++ przyjmuje następującą składnię:
datatype *variable_name;
- Typ danych jest typem podstawowym wskaźnika, który musi być prawidłowy C++ typ danych.
- Nazwa_zmiennej powinna być nazwą zmiennej wskaźnikowej.
- Gwiazdka użyta powyżej do deklaracji wskaźnika jest podobna do gwiazdki używanej do wykonywania operacji mnożenia. To gwiazdka oznacza zmienną jako wskaźnik.
Oto przykład prawidłowych deklaracji wskaźników w C++:
int *x; // a pointer to integer double *x; // a pointer to double float *x; // a pointer to float char *ch // a pointer to a character
Operator odniesienia (&) i operator oddania (*)
Operator odniesienia (&) zwraca adres zmiennej.
Operator dereferencji (*) pomaga nam uzyskać wartość zapisaną w danym adresie pamięci.
Na przykład:
Jeżeli mamy zmienną o nazwie num, zapisaną pod adresem 0x234 i przechowującą wartość 28.
Operator odniesienia (&) zwróci wartość 0x234.
Operator dereferencji (*) zwróci wartość 5.
1 przykład:
#include <iostream> using namespace std; int main() { int x = 27; int *ip; ip = &x; cout << "Value of x is : "; cout << x << endl; cout << "Value of ip is : "; cout << ip<< endl; cout << "Value of *ip is : "; cout << *ip << endl; return 0; }
Wyjście:
Jak to działa:
Oto zrzut ekranu kodu:
Wyjaśnienie kodu:
- Zaimportuj plik nagłówkowy iostream. Dzięki temu będziemy mogli korzystać z funkcji zdefiniowanych w pliku nagłówkowym bez popełniania błędów.
- Dołącz przestrzeń nazw std, aby używać jej klas bez wywoływania jej.
- Wywołaj funkcję main(). Logikę programu należy dodać w treści tej funkcji. { oznacza początek treści funkcji.
- Zadeklaruj zmienną całkowitą x i przypisz jej wartość 27.
- Zadeklaruj zmienną wskaźnikową *ip.
- Zapisz adres zmiennej x w zmiennej wskaźnikowej.
- Wydrukuj tekst na konsoli.
- Wydrukuj wartość zmiennej x na ekranie.
- Wydrukuj tekst na konsoli.
- Wydrukuj adres zmiennej x. Wartość adresu została zapisana w zmiennej ip.
- Wydrukuj tekst na konsoli.
- Wydrukuj wartość przechowywaną pod adresem wskaźnika.
- Program powinien zwrócić wartość po pomyślnym wykonaniu.
- Koniec treści funkcji main().
Wskaźniki i tablice
Tablice i wskaźniki działają w oparciu o pokrewną koncepcję. Pracując z tablicami zawierającymi wskaźniki, należy zwrócić uwagę na różne rzeczy. Sama nazwa tablicy oznacza adres podstawowy tablicy. Oznacza to, że aby przypisać adres tablicy do wskaźnika, nie należy używać ampersandu (&).
Na przykład:
p = arr;
Powyższe jest poprawne, ponieważ arr reprezentuje adres tablic. Oto kolejny przykład:
p = &arr;
Powyższe jest nieprawidłowe.
Możemy niejawnie przekonwertować tablicę na wskaźnik. Na przykład:
int arr [20]; int * ip;
Poniżej przedstawiono prawidłową operację:
ip = arr;
Po powyższej deklaracji ip i arr będą równoważne i będą miały wspólne właściwości. Można jednak przypisać inny adres do ip, ale do arr nie możemy przypisać niczego.
2 przykład:
Ten przykład pokazuje, jak poruszać się po tablicy za pomocą wskaźników:
#include <iostream> using namespace std; int main() { int *ip; int arr[] = { 10, 34, 13, 76, 5, 46 }; ip = arr; for (int x = 0; x < 6; x++) { cout << *ip << endl; ip++; } return 0; }
Wyjście:
Oto zrzut ekranu kodu:
Wyjaśnienie kodu:
- Zadeklaruj zmienną wskaźnikową w postaci liczby całkowitej ip.
- Zadeklaruj tablicę o nazwie arr i zapisz w niej 6 liczb całkowitych.
- Przypisz arr do ip. IP i arr staną się równoważne.
- Utwórz pętlę for. Zmienna pętli x została utworzona w celu iteracji po elementach tablicy o indeksach od 0 do 5.
- Wydrukuj wartości zapisane pod adresem IP wskaźnika. Na każdą iterację zostanie zwrócona jedna wartość i łącznie zostanie wykonanych 6 powtórzeń. Koniec jest a C++ słowo kluczowe oznaczające linię końcową. Akcja ta pozwala na przeniesienie kursora do następnej linii po wydrukowaniu każdej wartości. Każda wartość zostanie wydrukowana w osobnej linii.
- Aby przenieść wskaźnik do następnej pozycji int po każdej iteracji.
- Koniec pętli for.
- Program musi zwrócić coś po pomyślnym wykonaniu.
- Koniec treści funkcji main().
Wskaźnik NULL
Jeśli nie ma dokładnego adresu, który ma zostać przypisany, wówczas zmiennej wskaźnikowej można przypisać wartość NULL. Należy tego dokonać w trakcie składania oświadczenia. Taki wskaźnik nazywany jest wskaźnikiem zerowym. Jego wartość wynosi zero i jest zdefiniowana w wielu standardowych bibliotekach, takich jak iostream.
3 przykład:
#include <iostream> using namespace std; int main() { int *ip = NULL; cout << "Value of ip is: " << ip; return 0; }
Wyjście:
Oto zrzut ekranu kodu:
Wyjaśnienie kodu:
- Zadeklaruj zmienną wskaźnikową ip i przypisz jej wartość NULL.
- Wydrukuj wartość zmiennej wskaźnikowej ip obok tekstu na konsoli.
- Program musi zwrócić wartość po pomyślnym zakończeniu.
- Koniec treści funkcji main().
Wskaźniki zmiennych
Wraz z C++, możesz manipulować danymi bezpośrednio z pamięci komputera.
Przestrzeń pamięci można przydzielać lub ponownie przypisywać według własnego uznania. Jest to możliwe dzięki zmiennym wskaźnikowym.
Zmienne wskaźnikowe wskazują konkretny adres w pamięci komputera, na który wskazuje inna zmienna.
Można to zadeklarować w następujący sposób:
int *p;
Lub,
int* p;
W twoim przykładzie zadeklarowaliśmy zmienną wskaźnikową p.
Będzie przechowywać adres pamięci.
Gwiazdka jest operatorem dereferencji oznaczającym wskaźnik do.
Wskaźnik p wskazuje wartość całkowitą w adresie pamięci.
4 przykład:
#include <iostream> using namespace std; int main() { int *p, x = 30; p = &x; cout << "Value of x is: " << *p; return 0; }
Wyjście:
Oto zrzut ekranu kodu:
Wyjaśnienie kodu:
- Zadeklaruj zmienną wskaźnikową p i zmienną x o wartości 30.
- Przypisz adres zmiennej x do p.
- Wydrukuj wartość zmiennej wskaźnikowej p obok tekstu na konsoli.
- Program musi zwrócić wartość po pomyślnym zakończeniu.
- Koniec treści funkcji main().
Zastosowanie wskaźników
Funkcje w C++ może zwrócić tylko jedną wartość. Ponadto, wszystkie zmienne zadeklarowane w funkcji są przydzielane na stosie wywołań funkcji. Gdy tylko funkcja zwróci wartość, wszystkie zmienne stosu zostaną zniszczone.
Argumenty do funkcji są przekazywane przez wartość, a wszelkie modyfikacje zmiennych nie zmieniają wartości rzeczywistych zmiennych, które są przekazywane. Poniższy przykład pomaga zilustrować tę koncepcję:-
5 przykład:
#include <iostream> using namespace std; void test(int*, int*); int main() { int a = 5, b = 5; cout << "Before changing:" << endl; cout << "a = " << a << endl; cout << "b = " << b << endl; test(&a, &b); cout << "\nAfter changing" << endl; cout << "a = " << a << endl; cout << "b = " << b << endl; return 0; } void test(int* n1, int* n2) { *n1 = 10; *n2 = 11; }
Wyjście:
Oto zrzut ekranu kodu:
Wyjaśnienie kodu:
- Utwórz prototyp funkcji o nazwie test, która będzie przyjmować dwa parametry całkowite.
- Wywołaj funkcję main(). Dodamy logikę programu do jego ciała.
- Zadeklaruj dwie zmienne całkowite aib, każda o wartości 5.
- Wydrukuj tekst na konsoli. Endl (linia końcowa) przesunie kursor, aby rozpocząć drukowanie w następnej linii.
- Wydrukuj wartość zmiennej a na konsoli wraz z innym tekstem. Endl (linia końcowa) przesunie kursor, aby rozpocząć drukowanie w następnej linii.
- Wydrukuj wartość zmiennej b na konsoli wraz z innym tekstem. Endl (linia końcowa) przesunie kursor, aby rozpocząć drukowanie w następnej linii.
- Utwórz funkcję o nazwie test(), która przyjmuje adresy zmiennych a i b jako parametry.
- Wydrukuj tekst na konsoli. \n utworzy nową pustą linię przed wydrukowaniem tekstu. Endl (linia końcowa) przesunie kursor, aby rozpocząć drukowanie w następnej linii po wydrukowaniu tekstu.
- Wydrukuj wartość zmiennej a na konsoli wraz z innym tekstem. Endl (linia końcowa) przesunie kursor, aby rozpocząć drukowanie w następnej linii.
- Wydrukuj wartość zmiennej b na konsoli wraz z innym tekstem. Endl (linia końcowa) przesunie kursor, aby rozpocząć drukowanie w następnej linii.
- Program musi zwrócić wartość po pomyślnym zakończeniu.
- Koniec treści funkcji main().
- Definiowanie funkcji test(). Funkcja powinna przyjmować dwie zmienne wskaźnikowe w postaci liczb całkowitych *n1 i *n2.
- Przypisanie zmiennej wskaźnikowej *n1 wartości 10.
- Przypisanie zmiennej wskaźnikowej *n2 wartości 11.
- Koniec treści funkcji test().
Mimo że w teście funkcji do zmiennych a i b przypisane są nowe wartości, po zakończeniu wywołania funkcji nie jest to odzwierciedlane w zewnętrznej funkcji main.
Używanie wskaźników jako argumentów funkcji pomaga przekazać rzeczywisty adres zmiennej w funkcji, a wszystkie zmiany dokonane na zmiennej zostaną odzwierciedlone w funkcji zewnętrznej.
W powyższym przypadku funkcja „test” ma adres zmiennych „a” i „b”. Te dwie zmienne są bezpośrednio dostępne z funkcji „test”, dlatego wszelkie zmiany dokonane w tych zmiennych są odzwierciedlane w funkcji wywołującej „main”.
Zalety używania wskaźników
Oto zalety/korzyści używania wskaźników
- Wskaźniki to zmienne przechowujące adresy innych zmienne w C++.
- Funkcja za pomocą wskaźników może modyfikować i zwracać więcej niż jedną zmienną.
- Pamięć można dynamicznie przydzielać i zwalniać za pomocą wskaźników.
- Wskaźniki pomagają uprościć złożoność programu.
- Szybkość wykonywania programu poprawia się dzięki użyciu wskaźników.
Podsumowanie
- Wskaźnik odnosi się do zmiennej przechowującej adres innej zmiennej.
- Każdy wskaźnik ma prawidłowy typ danych.
- Wskaźnik jest symboliczną reprezentacją adresu pamięci.
- Wskaźniki pozwalają programom symulować wywołanie przez odwołanie oraz tworzyć i manipulować dynamicznymi strukturami danych.
- Tablice i wskaźniki korzystają z powiązanej koncepcji.
- Nazwa tablicy oznacza podstawę tablicy.
- Jeśli chcesz przypisać adres tablicy do wskaźnika, nie używaj ampersandu (&).
- Jeśli nie ma konkretnego adresu do przypisania zmiennej wskaźnikowej, przypisz jej wartość NULL.