Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Operatory wskaźnika umożliwiają odbieranie adresu zmiennej (&), wyłuszczanie wskaźnika (*), porównywanie wartości wskaźnika oraz dodawanie lub odejmowanie wskaźników i liczb całkowitych.
Do pracy ze wskaźnikami służą następujące operatory:
- Operator jednoargumentowy
&(adres-of): aby uzyskać adres zmiennej - Operator jednoargumentowy
*(pośredni wskaźnik): aby uzyskać zmienną wskazywaną przez wskaźnik - Operatory
->(dostęp do składowych) i[](dostęp do elementów) - Operatory
+arytmetyczne ,-,++i-- - Operatory
==porównania, ,!=<,>,<=i>=
Aby uzyskać informacje o typach wskaźników, zobacz Typy wskaźników.
Uwaga
Każda operacja ze wskaźnikami wymaga niebezpiecznego kontekstu. Kod zawierający niebezpieczne bloki należy skompilować za pomocą opcji kompilatora AllowUnsafeBlocks .
Operator adresowy i
Operator jednoargumentowy & zwraca adres operandu:
unsafe
{
int number = 27;
int* pointerToNumber = &number;
Console.WriteLine($"Value of the variable: {number}");
Console.WriteLine($"Address of the variable: {(long)pointerToNumber:X}");
}
// Output is similar to:
// Value of the variable: 27
// Address of the variable: 6C1457DBD4
Operand & operatora musi być zmienną stałą.
Zmienne stałe to zmienne, które znajdują się w lokalizacjach przechowywania, które nie mają wpływu na działanie modułu odśmiecywania pamięci. W poprzednim przykładzie zmienna lokalna jest zmienną number stałą, ponieważ znajduje się na stosie. Zmienne, które znajdują się w lokalizacjach przechowywania, których może dotyczyć moduł odśmiecający pamięci (na przykład przeniesiony) są nazywane zmiennymi wymiennymi . Pola obiektów i elementy tablicy to przykłady zmiennych wymiennych. Adres zmiennej wymiennej można uzyskać, jeśli "naprawisz" lub "przypnij", będzie ona zawierać instrukcję fixed. Uzyskany adres jest prawidłowy tylko wewnątrz bloku instrukcji fixed . W poniższym przykładzie pokazano, jak używać fixed instrukcji i & operatora:
unsafe
{
byte[] bytes = { 1, 2, 3 };
fixed (byte* pointerToFirst = &bytes[0])
{
// The address stored in pointerToFirst
// is valid only inside this fixed statement block.
}
}
Nie można uzyskać adresu stałej ani wartości.
Aby uzyskać więcej informacji na temat zmiennych stałych i wymiennych, zobacz sekcję Zmienne stałe i ruchome specyfikacji języka C#.
Operator binarny & oblicza logiczne AND jego operandów logicznych lub bitowych operatorów logicznych AND z operandów całkowitych.
Operator pośredni wskaźnika *
Operator * jednoargumentowego wskaźnika pośredniego uzyskuje zmienną, do której wskazuje operand. Jest on również znany jako operator wyłudzenia. Operand * operatora musi być typu wskaźnika.
unsafe
{
char letter = 'A';
char* pointerToLetter = &letter;
Console.WriteLine($"Value of the `letter` variable: {letter}");
Console.WriteLine($"Address of the `letter` variable: {(long)pointerToLetter:X}");
*pointerToLetter = 'Z';
Console.WriteLine($"Value of the `letter` variable after update: {letter}");
}
// Output is similar to:
// Value of the `letter` variable: A
// Address of the `letter` variable: DCB977DDF4
// Value of the `letter` variable after update: Z
Nie można zastosować * operatora do wyrażenia typu void*.
Operator binarny * oblicza iloczyn operandów liczbowych.
Operator dostępu do elementu członkowskiego wskaźnika —>
Operator -> łączy wskaźnik pośredni i dostęp do składowych. Oznacza to, że jeśli x jest wskaźnikiem typu T* i y jest dostępnym elementem członkowskim typu T, wyrażenie formularza
x->y
jest równoważny
(*x).y
W poniższym przykładzie pokazano użycie -> operatora:
public struct Coords
{
public int X;
public int Y;
public override string ToString() => $"({X}, {Y})";
}
public class PointerMemberAccessExample
{
public static unsafe void Main()
{
Coords coords;
Coords* p = &coords;
p->X = 3;
p->Y = 4;
Console.WriteLine(p->ToString()); // output: (3, 4)
}
}
Nie można zastosować -> operatora do wyrażenia typu void*.
Operator dostępu do elementu wskaźnika []
W przypadku wyrażenia p typu wskaźnika dostęp do elementu wskaźnika formularza p[n] jest obliczany jako *(p + n), gdzie n musi być typu niejawnie konwertowany na int, , uintlonglub ulong. Aby uzyskać informacje o zachowaniu + operatora ze wskaźnikami, zobacz Dodawanie lub odejmowanie wartości całkowitej do lub z sekcji wskaźnika .
W poniższym przykładzie pokazano, jak uzyskać dostęp do elementów tablicy za pomocą wskaźnika i [] operatora:
unsafe
{
char* pointerToChars = stackalloc char[123];
for (int i = 65; i < 123; i++)
{
pointerToChars[i] = (char)i;
}
Console.Write("Uppercase letters: ");
for (int i = 65; i < 91; i++)
{
Console.Write(pointerToChars[i]);
}
}
// Output:
// Uppercase letters: ABCDEFGHIJKLMNOPQRSTUVWXYZ
W poprzednim przykładzie stackalloc wyrażenie przydziela blok pamięci na stosie.
Uwaga
Operator dostępu elementu wskaźnika nie sprawdza błędów braku ograniczeń.
Nie można użyć [] do uzyskiwania dostępu do elementu wskaźnika z wyrażeniem typu void*.
Możesz również użyć operatora do uzyskiwania [] dostępu do elementu tablicy lub indeksatora.
Operatory arytmetyczne wskaźnika
Następujące operacje arytmetyczne można wykonać za pomocą wskaźników:
- Dodawanie lub odejmowanie wartości całkowitej do lub ze wskaźnika
- Odejmowanie dwóch wskaźników
- Inkrementacja lub dekrementacja wskaźnika
Nie można wykonać tych operacji za pomocą wskaźników typu void*.
Aby uzyskać informacje na temat obsługiwanych operacji arytmetycznych z typami liczbowymi, zobacz Operatory arytmetyczne.
Dodawanie lub odejmowanie wartości całkowitej do lub ze wskaźnika
Dla wskaźnika p typu i wyrażenia T* typu niejawnie konwertowanego na n, int, uintlub long, dodawanie i odejmowanie są definiowane ulong w następujący sposób:
- Oba
p + nwyrażenia in + pgenerują wskaźnik typuT*, który wynika z dodawanian * sizeof(T)do adresu podanego przezpelement . - Wyrażenie
p - ngeneruje wskaźnik typuT*, który wynika z odejmowanian * sizeof(T)z adresu podanego przezp.
Operator sizeof uzyskuje rozmiar typu w bajtach.
W poniższym przykładzie pokazano użycie + operatora ze wskaźnikiem:
unsafe
{
const int Count = 3;
int[] numbers = new int[Count] { 10, 20, 30 };
fixed (int* pointerToFirst = &numbers[0])
{
int* pointerToLast = pointerToFirst + (Count - 1);
Console.WriteLine($"Value {*pointerToFirst} at address {(long)pointerToFirst}");
Console.WriteLine($"Value {*pointerToLast} at address {(long)pointerToLast}");
}
}
// Output is similar to:
// Value 10 at address 1818345918136
// Value 30 at address 1818345918144
Odejmowanie wskaźnika
W przypadku dwóch wskaźników p1 i p2 typu T*wyrażenie p1 - p2 generuje różnicę między adresami podanymi przez p1 i p2 podzielonymi przez sizeof(T). Typ wyniku to long. Oznacza to, p1 - p2 że jest obliczany jako ((long)(p1) - (long)(p2)) / sizeof(T).
W poniższym przykładzie pokazano odejmowanie wskaźnika:
unsafe
{
int* numbers = stackalloc int[] { 0, 1, 2, 3, 4, 5 };
int* p1 = &numbers[1];
int* p2 = &numbers[5];
Console.WriteLine(p2 - p1); // output: 4
}
Inkrementacja i dekrementacja wskaźnika
Operator ++inkrementacji dodaje wartość 1 do operandu wskaźnika.
-- Operator dekrementacji odejmuje 1 od operandu wskaźnika.
Oba operatory są obsługiwane w dwóch formach: postfiks (p++ i ) i p--prefiks (++p i --p). Wynik p++ i p-- jest wartością pprzed operacją. Wynik ++p i --p jest wartością ppo operacji.
W poniższym przykładzie pokazano zachowanie operatorów przyrostka postfiksu i prefiksu:
unsafe
{
int* numbers = stackalloc int[] { 0, 1, 2 };
int* p1 = &numbers[0];
int* p2 = p1;
Console.WriteLine($"Before operation: p1 - {(long)p1}, p2 - {(long)p2}");
Console.WriteLine($"Postfix increment of p1: {(long)(p1++)}");
Console.WriteLine($"Prefix increment of p2: {(long)(++p2)}");
Console.WriteLine($"After operation: p1 - {(long)p1}, p2 - {(long)p2}");
}
// Output is similar to
// Before operation: p1 - 816489946512, p2 - 816489946512
// Postfix increment of p1: 816489946512
// Prefix increment of p2: 816489946516
// After operation: p1 - 816489946516, p2 - 816489946516
Operatory porównania wskaźników
Operatory ==, , !=, <>, <=i umożliwiają >= porównywanie operandów dowolnego typu wskaźnika, w tym void*. Te operatory porównują adresy podane przez dwa operandy tak, jakby były niepodpisane liczby całkowite.
Aby uzyskać informacje o zachowaniu tych operatorów dla operandów innych typów, zobacz artykuły Operatory równości i Operatory porównania.
Kolejność wykonywania działań
Następujące operatory powiązane ze wskaźnikiem orders zaczynają się od najwyższego pierwszeństwa do najniższego:
- Operatory przyrostkowe i dekrementacji
x++x--oraz->operatory i[] - Operatory inkrementacji i dekrementacji
++x--xprefiksu&oraz operatory i* - Operatory i
+addytywne- - Porównanie
<operatorów , ,><=i>= - Równość
==i!=operatory
Użyj nawiasów, (), aby zmienić kolejność oceny narzuconą przez pierwszeństwo operatora.
Aby uzyskać pełną listę operatorów języka C# uporządkowanych według poziomu pierwszeństwa, zobacz sekcję Pierwszeństwo operatora w artykule Operatory języka C#.
Przeciążenie operatora
Typ zdefiniowany przez użytkownika nie może przeciążyć operatorów &powiązanych ze wskaźnikiem , *, ->i [].
specyfikacja języka C#
Aby uzyskać więcej informacji, zobacz następujące sekcje specyfikacji języka C#:
- Zmienne stałe i przenoszone
- Operator address-of
- Pośredni wskaźnik
- Dostęp do elementu członkowskiego wskaźnika
- Dostęp do elementu wskaźnika
- Arytmetyka wskaźnika
- Inkrementacja i dekrementacja wskaźnika
- Porównanie wskaźników