Etap 11: Arytmetyka wskaźników w C++
Zrozumienie, jak C++ operuje na adresach pamięci. Dowiedz się, dlaczego ptr++ to coś więcej niż dodanie jedynki.
Arytmetyka wskaźników: Poruszanie się po pamięci
Arytmetyka wskaźników to mechanizm pozwalający na wykonywanie operacji dodawania i odejmowania na adresach pamięci. Jest to fundament działania tablic w C++. Kluczową zasadą, którą musisz zapamiętać na kolokwium, jest to, że operacje te są skalowane przez rozmiar typu danych, na który wskazuje wskaźnik.
1. Inkrementacja i dekrementacja (ptr++, ptr--)
Kiedy zwiększasz wskaźnik o 1 (ptr++), nie przesuwasz się o jeden bajt w pamięci. Przesuwasz się o tyle bajtów, ile zajmuje dany typ danych (czyli o sizeof(typ)).
- Jeśli
intzajmuje 4 bajty, toptr++zwiększy adres o 4. - Jeśli
doublezajmuje 8 bajtów, toptr++zwiększy adres o 8.
int tab[] = {10, 20, 30};
int *p = tab; // wskazuje na tab[0]
p++; // teraz p wskazuje na tab[1]
std::cout << *p; // Wypisze 202. Dodawanie i odejmowanie liczb całkowitych
Możesz przesunąć wskaźnik o dowolną liczbę elementów, dodając lub odejmując od niego liczbę całkowitą.
int *p = &tab[0];
int *p2 = p + 2; // p2 wskazuje teraz na tab[2]3. Odejmowanie wskaźników od siebie
Jeśli masz dwa wskaźniki wskazujące na elementy tej samej tablicy, możesz je od siebie odjąć. Wynikiem nie jest liczba bajtów, ale liczba elementów znajdujących się między nimi.
int *p_start = &tab[0];
int *p_end = &tab[2];
int dystans = p_end - p_start; // Wynik: 24. Relacja między wskaźnikiem a tablicą
W C++ zapis tab[i] jest jedynie „lukrem syntaktycznym” dla operacji wskaźnikowej. Kompilator zawsze zamienia to na:
*(tab + i)
Oznacza to, że możesz iterować po tablicy używając samego wskaźnika, co często jest wymagane w zadaniach niskopoziomowych.
const int N = 3;
int liczby[N] = {100, 200, 300};
int *ptr = liczby;
for(int i = 0; i < N; i++) {
std::cout << *(ptr + i) << " "; // To samo co ptr[i] lub liczby[i]
}Pułapki na kolokwium
- Mnożenie i dzielenie: Nie wolno mnożyć ani dzielić wskaźników. Operacje takie jak
ptr * 2spowodują błąd kompilacji. - Dodawanie wskaźników: Nie można dodać wskaźnika do wskaźnika (
ptr1 + ptr2). To nie ma sensu logicznego (jaki adres miałby powstać?). - Poza zakresem: Arytmetyka pozwala na ustawienie wskaźnika poza tablicę (np.
tab + 100dla 5-elementowej tablicy). C++ nie zablokuje Cię przed tym, ale próba dereferencji (*) takiego adresu skończy się awarią programu. - Wskaźniki typu void*: Na wskaźnikach typu
void*nie można wykonywać arytmetyki, ponieważ kompilator nie wie, o jaki rozmiar (sizeof) ma przesunąć adres.
Przykład: Odwracanie tablicy wskaźnikami
void odwroc(int *lewy, int *prawy) {
while (lewy < prawy) {
int temp = *lewy;
*lewy = *prawy;
*prawy = temp;
lewy++;
prawy--;
}
}Może Cię zainteresować
Etap 10: Wskaźniki, operator adresu i dereferencji
Zrozumienie fundamentów adresowania pamięci w C++: jak działają wskaźniki i operatory niskopoziomowe.
Etap 3: Tablice automatyczne, jednowymiarowe w C++
Przewodnik po statycznych tablicach jednowymiarowych: deklaracja, inicjalizacja i bezpieczna iteracja.
Etap 6: Obsługa napisów w stylu C (char[])
Przewodnik po niskopoziomowym przetwarzaniu napisów jako tablic znaków zakończonych zerem, zgodnie z ograniczeniami kolokwium.