Operátory související s ukazateli (Referenční dokumentace jazyka C#)
Pro práci s ukazateli můžete použít následující operátory:
- Unární operátor
&(Address-of) : pro získání adresy proměnné - Unární operátor
*(indirekce ukazatele) : pro získání proměnné, na kterou odkazuje ukazatel - Operátory
->(přístup ke členům) a[](přístup k prvkům) - Aritmetické operátory
+,-,++a-- - Operátory porovnání
==,!=,,,<><=a>=
Informace o typech ukazatelů naleznete v tématu typy ukazatelů.
Poznámka
Jakákoli operace s ukazateli vyžaduje nezabezpečený kontext. Kód, který obsahuje nebezpečné bloky, musí být zkompilován pomocí možnosti kompilátoru AllowUnsafeBlocks .
Address-of – operátor &
Unární & operátor vrátí adresu svého 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
Operandem & operátoru musí být pevná proměnná. Pevné proměnné jsou proměnné, které jsou umístěny v umístěních úložiště, která nejsou ovlivněna operací uvolňování paměti. V předchozím příkladu je místní proměnná number pevnou proměnnou, protože se nachází v zásobníku. Proměnné, které jsou umístěné v umístění úložiště, které může být ovlivněno systémem uvolňování paměti (například přemístěné), se nazývají pohyblivé proměnné. V příkladech pohyblivých proměnných jsou pole objektů a prvky pole. Pokud "opravíte" nebo "PIN", můžete získat adresu pohyblivé proměnné s fixed příkazem. Získaná adresa je platná pouze uvnitř bloku fixed příkazu. Následující příklad ukazuje, jak použít fixed příkaz a & operátor:
unsafe
{
byte[] bytes = { 1, 2, 3 };
fixed (byte* pointerToFirst = &bytes[0])
{
// The address stored in pointerToFirst
// is valid only inside this fixed statement block.
}
}
Nemůžete získat adresu konstanty nebo hodnoty.
Další informace o pevných a pohyblivých proměnných naleznete v části pevné a mobilní proměnné specifikace jazyka C#.
Binární & operátor vypočítá logický a jeho logický operandy nebo bitovou logickou hodnotu a její celočíselné operandy.
Operátor dereference ukazatele *
Operátor dereference unárního ukazatele * získá proměnnou, do které se operandy vykáže. Označuje se také jako operátor odkázání. Operand * operátoru musí být typu ukazatele.
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
Operátor nelze použít * na výraz typu void* .
Binární * operátor vypočítá součin svých číselných operandů.
Operátor přístupu členů ukazatele->
->Operátor kombinuje nepřímý odkaz na ukazatele a přístup ke členu. To znamená, že pokud x je ukazatel typu T* a y je přístupným členem typu T , výraz formuláře
x->y
je ekvivalentem
(*x).y
Následující příklad ukazuje použití -> operátoru:
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)
}
}
Operátor nelze použít -> na výraz typu void* .
Operátor přístupu k elementu ukazatele []
Pro výraz p typu ukazatele je přístup k elementu formuláře p[n] vyhodnocen jako *(p + n) , kde n musí být typu implicitně převoditelný na int , uint , long nebo ulong . Informace o chování + operátoru s ukazateli naleznete v části sčítání nebo odčítání celočíselné hodnoty nebo z ukazatele na ukazatel .
Následující příklad ukazuje, jak přistupovat k prvkům pole s ukazatelem a [] operátorem:
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
V předchozím příkladu stackalloc výraz přiděluje blok paměti v zásobníku.
Poznámka
Operátor přístupu elementu ukazatele nekontroluje chyby mimo hranice.
Nemůžete použít [] pro přístup k prvku ukazatele s výrazem typu void* .
Operátor můžete použít také [] pro prvek pole nebo pro přístup k indexeru.
Aritmetické operátory ukazatele
S ukazateli můžete provádět následující aritmetické operace:
- Přidat nebo odečíst celočíselnou hodnotu do nebo z ukazatele
- Odečíst dva ukazatele
- Zvýšení nebo snížení ukazatele
Tyto operace nelze provést s ukazateli typu void* .
Informace o podporovaných aritmetických operacích s číselnými typy naleznete v tématu aritmetické operátory.
Sčítání nebo odečítání celočíselné hodnoty do nebo z ukazatele
Pro ukazatel p typu T* a výraz n typu implicitně převoditelné na int , uint , long nebo ulong sčítání a odčítání jsou definovány takto:
- Oba
p + nn + pvýrazy a vytvoří ukazatel typuT*, který je výsledkem přidánín * sizeof(T)na adresu danou adresoup. p - nVýraz vytvoří ukazatel typuT*, který je výsledkem odečtenín * sizeof(T)od adresy uvedené vp.
sizeof Operátor získá velikost typu v bajtech.
Následující příklad ukazuje použití + operátoru s ukazatelem:
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
Odečtení ukazatele
Pro dva ukazatele p1 a p2 typ je T* výsledkem výrazu p1 - p2 rozdíl mezi adresami předanými p1 a p2 dělenou sizeof(T) . Typ výsledku je long . To znamená, že p1 - p2 je vypočítávána jako ((long)(p1) - (long)(p2)) / sizeof(T) .
Následující příklad ukazuje odčítání ukazatele:
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
}
Zvýšení a snížení ukazatele
++Operátor přírůstku přidá hodnotu 1 k operandu ukazatele. --Operátor snížení odečte 1 od jeho operandu ukazatele.
Oba operátory jsou podporovány ve dvou formulářích: přípona ( p++ a p-- ) a předpona ( ++p a --p ). Výsledek p++ a p-- je hodnota p před operací. Výsledek ++p a --p je hodnota p po operaci.
Následující příklad demonstruje chování obou operátorů přípony i prefixu:
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
Operátory porovnání ukazatelů
== != Operátory,,,, a můžete použít < > <= >= k porovnání operandů libovolného typu ukazatele, včetně void* . Tyto operátory porovnávají adresy zadané dvěma operandy, jako by šlo o celá čísla bez znaménka.
Informace o chování těchto operátorů pro operandy jiných typů naleznete v článcích operátory rovnosti a operátory porovnání .
Priorita operátorů
Následující seznam uvádí operátory související s ukazateli počínaje od nejvyšší priority k nejnižší:
- Operátory přírůstku
x++a snížení příponyx--a->[]operátory a - Operátory přírůstku
++xa snížení předpony--xa&*operátory a - Doplňková
+a-operátor <Operátory porovnání,,><=a>=- Rovnost
==a!=operátory
Použijte závorky, () Chcete-li změnit pořadí vyhodnocování stanovené předností operátorů.
Úplný seznam operátorů jazyka C# seřazených podle priority úrovně naleznete v části Priorita operátorů v článku operátory jazyka c# .
Přetížení operátoru
Uživatelsky definovaný typ nemůže přetížit operátory související s ukazatelem & , * , -> a [] .
specifikace jazyka C#
Další informace naleznete v následujících oddílech specifikace jazyka C#:
- Pevné a mobilní proměnné
- Operátor address-of
- Indirekce ukazatele
- Přístup ke členu ukazatele
- Přístup k prvku ukazatele
- Aritmetika ukazatele
- Zvýšení a snížení ukazatele
- Porovnání ukazatelů