Korzystając z IntelliSense i patrząc na kod innych osób, natknąłem się na ten IntPtr
typ; za każdym razem, gdy trzeba było go użyć, po prostu wstawiłem null
lub IntPtr.Zero
i stwierdziłem, że większość funkcji działa. Co to właściwie jest i kiedy / dlaczego jest używane?
171
IntPtr
ma sens, ponieważ jest to liczba całkowita (jak w matematycznej liczbie całkowitej) i wskaźnik (jak we wskaźniku).Int
Część ma niewiele wspólnego z typem int - to pojęcie, a nie specyficzny typ. Chociaż szczerze mówiąc, jedyną rzeczą, o której mówi specyfikacja CLI, jest to, że jest to rzeczywiście „całkowity, natywny rozmiar”. No cóż :)Jest to typ wartości wystarczająco duży, aby przechowywać adres pamięci używany w kodzie natywnym lub niebezpiecznym, ale nie można go bezpośrednio używać jako adresu pamięci w bezpiecznym kodzie zarządzanym.
Możesz użyć,
IntPtr.Size
aby dowiedzieć się, czy pracujesz w procesie 32-bitowym, czy 64-bitowym, ponieważ będzie to odpowiednio 4 lub 8 bajtów.źródło
IntPtr
jest również używany do reprezentowania uchwytów, które są 32-bitowe, niezależnie od architektury (choćSize
w tym przypadku nadal mówi 8). Specyfikacja CLI mówi tylko, że jest to liczba całkowita o „rodzimym rozmiarze”, ale tak naprawdę to niewiele mówi.Oto przykład:
Piszę program w C #, który łączy się z szybkim aparatem. Aparat ma własny sterownik, który pobiera zdjęcia i automatycznie ładuje je do pamięci komputera.
Więc kiedy jestem gotowy, aby wprowadzić najnowszy obraz do mojego programu do pracy, sterownik aparatu dostarcza mi IntPtr, gdzie obraz jest JUŻ przechowywany w pamięci fizycznej, więc nie muszę tracić czasu / zasobów na tworzenie kolejnego blok pamięci do przechowywania obrazu, który jest już w pamięci. IntPtr po prostu pokazuje mi, gdzie obraz już jest.
źródło
Bezpośrednia interpretacja
IntPtr jest liczbą całkowitą , która ma taką samą wielkość jak wskaźnik .
Możesz użyć IntPtr do przechowywania wartości wskaźnika w typie innym niż wskaźnik. Ta funkcja jest ważna w .NET, ponieważ używanie wskaźników jest bardzo podatne na błędy, a zatem w większości kontekstów jest niedozwolone. Zezwalając na przechowywanie wartości wskaźnika w „bezpiecznym” typie danych, przepływ między niebezpiecznymi segmentami kodu może być realizowany w bezpieczniejszym kodzie wysokiego poziomu - lub nawet w języku .NET, który nie obsługuje bezpośrednio wskaźników.
Rozmiar IntPtr zależy od platformy, ale ten szczegół rzadko musi być brany pod uwagę, ponieważ system automatycznie użyje prawidłowego rozmiaru.
Nazwa „IntPtr” jest myląca - coś takiego jak
Handle
mogłoby być bardziej odpowiednie. Moje początkowe przypuszczenie było takie, że „IntPtr” był wskaźnikiem do liczby całkowitej. Dokumentacja MSDN dotycząca IntPtr zawiera nieco tajemnicze szczegóły, nigdy nie dostarczając zbyt wielu informacji na temat znaczenia nazwy.Alternatywna perspektywa
An
IntPtr
jest wskaźnikiem z dwoma ograniczeniami:Innymi słowy, an
IntPtr
jest podobny do avoid*
- ale z dodatkową funkcją, której może (ale nie powinien) być używany do podstawowych działań arytmetycznych wskaźników.Aby wyłuskać odwołanie
IntPtr
, możesz albo rzutować go na prawdziwy wskaźnik (operację, która może być wykonywana tylko w "niebezpiecznych" kontekstach) lub możesz przekazać ją do procedury pomocniczej, takiej jak te dostarczane przezInteropServices.Marshal
klasę. UżywanieMarshal
klasy daje iluzję bezpieczeństwa, ponieważ nie wymaga przebywania w jawnym kontekście „niebezpiecznego”. Nie eliminuje jednak ryzyka awarii, które jest nieodłącznie związane ze stosowaniem wskaźników.źródło
Co to jest wskaźnik?
We wszystkich językach, wskaźnik jest typem zmiennej, która przechowuje adres pamięci, a można też poprosić ich, aby powiedzieć wam adres są wskazującego lub wartości pod adresem są wskazującego.
Wskaźnik można traktować jako rodzaj zakładki. Z wyjątkiem tego, że zamiast szybkiego przeskakiwania do strony w książce, wskaźnik służy do śledzenia lub mapowania bloków pamięci.
Wyobraź sobie pamięć twojego programu dokładnie jako jedną dużą tablicę 65535 bajtów.
Wskaźniki wskazują posłusznie
Wskaźniki pamiętają po jednym adresie pamięci, dlatego każdy z nich wskazuje na pojedynczy adres w pamięci.
Jako grupa, wskaźniki zapamiętują i przywołują adresy pamięci, wykonując każde polecenie do znudzenia.
Jesteś ich królem.
Wskaźniki w C #
Również specyficzne dla języka C # wskaźniki są typu int i dlatego są podpisane.
Nie możesz jednak używać adresów ponumerowanych ujemnie, ani nie możesz uzyskać dostępu do adresu powyżej 65534. Każda próba zrobienia tego spowoduje zgłoszenie wyjątku System.AccessViolationException.
Wskaźnik o nazwie MyPointer jest zadeklarowany w następujący sposób:
Wskaźnik w C # to int, ale adresy pamięci w C # zaczynają się od 0 i rozciągają się aż do 65534.
Ze spiczastymi przedmiotami należy obchodzić się ze szczególną ostrożnością
Słowo niebezpieczne ma cię przestraszyć i nie bez powodu: wskaźniki są spiczastymi przedmiotami, a spiczastymi przedmiotami, takimi jak miecze, topory, wskaźniki itp. Należy obchodzić się ze szczególną ostrożnością.
Wskaźniki dają programiście ścisłą kontrolę nad systemem. Dlatego popełnione błędy mogą mieć poważniejsze konsekwencje.
Aby używać wskaźników, niebezpieczny kod musi być włączony we właściwościach programu, a wskaźniki muszą być używane wyłącznie w metodach lub blokach oznaczonych jako niebezpieczne.
Przykład niebezpiecznego bloku
Jak używać wskaźników
Gdy zmienne lub obiekty są deklarowane lub tworzone, są one przechowywane w pamięci.
int *MyPointer;
MyPointer = &MyVariable;
Po przypisaniu adresu do wskaźnika obowiązują następujące zasady:
MyPointer = &MyVariable; // Set MyPointer to point at MyVariable
"MyPointer is pointing at " + *MyPointer;
Ponieważ wskaźnik jest zmienną, która przechowuje adres pamięci, ten adres pamięci może być przechowywany w zmiennej wskaźnikowej.
Przykład ostrożnego i odpowiedzialnego wykorzystania wskaźników
Zwróć uwagę, że typ wskaźnika to int. Dzieje się tak, ponieważ C # interpretuje adresy pamięci jako liczby całkowite (int).
Dlaczego jest to int zamiast uint?
Nie ma dobrego powodu.
Po co używać wskaźników?
Wskaźniki to świetna zabawa. Ponieważ tak duża część komputera jest kontrolowana przez pamięć, wskaźniki dają programiście większą kontrolę nad pamięcią programu.
Monitorowanie pamięci.
Użyj wskaźników do odczytywania bloków pamięci i monitorowania zmian wskazywanych wartości w czasie.
Zmień te wartości odpowiedzialnie i śledź, jak zmiany wpływają na Twój komputer.
źródło
65534
wydaje się bardzo błędny jako zakres wskaźnika. Powinieneś podać odniesienie.System.IntPtr
. Chciałbym zobaczyć zaktualizowaną odpowiedź na końcu wyjaśniającą, co równieżSystem.IntPtr
i jak odnosi się do niebezpiecznych wskaźników w C # proszę.MSDN mówi nam:
http://msdn.microsoft.com/en-us/library/system.intptr(VS.71).aspx
źródło
Cóż, to jest strona MSDN, która zajmuje się
IntPtr
.Pierwsza linia brzmi:
Co do tego, jaki wskaźnik lub uchwyt jest na stronie, stwierdza:
Wskaźnik to odniesienie do obszaru pamięci, w którym znajdują się interesujące Cię dane.
Uchwyt może być identyfikatorem obiektu i jest przekazywany między metodami / klasami, gdy obie strony potrzebują dostępu do tego obiektu.
źródło
An
IntPtr
to typ wartości, który jest używany głównie do przechowywania adresów lub uchwytów pamięci. Wskaźnik jest adresem pamięci. Wskaźnik może być wpisany (np.int*
) Lub bez typu (npvoid*
.). Uchwyt systemu Windows jest to wartość, która jest zwykle taki sam rozmiar (lub mniejszy) niż adres pamięci i reprezentuje zasobów systemowych (np pliku lub okna).źródło