Historia pytania: W języku C wskaźniki to zmienne przechowujące adresy innych obiektów. Powstał problem: jak porównywać takie wartości, przecież pamięć może być przydzielona w najbardziej nieprzewidywalny sposób. Język zezwala na operację porównywania między wskaźnikami, ale nakłada szereg ograniczeń, aby zachowanie pozostało określone.
Problem: Poprawnie można porównywać tylko wskaźniki na elementy tej samej tablicy lub na ten sam obiekt. Porównanie wskaźników wskazujących na niezwiązane obiekty (różne zmienne lub przydzielone obszary pamięci, które nie są częścią wspólnej tablicy) jest zachowaniem niezdefiniowanym (undefined behavior).
Rozwiązanie: Należy unikać porównywania wskaźników między niezwiązanymi obszarami pamięci, korzystać z tego tylko w obrębie jednej tablicy/ciągu/bufora, a porównanie z NULL jest bezpieczne.
Przykład kodu:
#include <stdio.h> int main() { int arr[5] = {1, 2, 3, 4, 5}; int *p1 = &arr[1]; int *p2 = &arr[3]; if (p1 < p2) { printf("p1 wskazuje na wcześniejszy element tablicy niż p2\n"); } }
Kluczowe cechy:
1. Czy można porównywać wskaźniki uzyskane przez malloc, które odnoszą się do różnych bloków pamięci?
Nie, porównywanie takich wskaźników nie jest dozwolone — zachowanie nie jest określone przez standard. Dozwolone jest porównywanie tylko wskaźników do tego samego przydzielonego bloku pamięci lub z NULL.
2. Co zwraca porównanie wskaźników typu int i double, jeśli wskazują na różne zmienne, ale mają taką samą wartość liczbową?**
Porównanie jest możliwe tylko wtedy, gdy oba wskaźniki zostały rzutowane na ten sam typ i wskazują na ten sam obiekt. Jeśli tak nie jest, wynik jest nieokreślony — wartości adresów mogą być takie same, ale standard nie gwarantuje tego zachowania.
3. Czy poprawne jest porównywanie wskaźnika na pierwszy element tablicy z wskaźnikiem na jej koniec (na przykład, arr i arr + N)?
Tak, jest to poprawne. arr + N wskazuje na wyimaginowany element, który następuje po ostatnim, a kompilator gwarantuje, że arr <= arr + N.
Pracownik postanowił zaimplementować funkcję porównującą adresy w celu określenia, "czy wcześniej stworzono" dwie struktury, przydzielone z różnych kawałków pamięci.
Plusy:
Minusy:
Po przeglądzie wprowadzono sprawdzenie przynależności wskaźników do jednego bloku pamięci poprzez przydzielenie wszystkich struktur w wspólnym buforze i dalsze porównanie w dopuszczalnych granicach.
Plusy:
Minusy: