Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Operátory ukazatele umožňují vzít adresu proměnné (&), dereference ukazatele (*), porovnat hodnoty ukazatele a sčítat nebo odečítat ukazatele a celá čísla.
Referenční dokumentace jazyka C# dokumentuje naposledy vydané verze jazyka C#. Obsahuje také počáteční dokumentaci k funkcím ve verzi Public Preview pro nadcházející jazykovou verzi.
Dokumentace identifikuje všechny funkce, které byly poprvé představeny v posledních třech verzích jazyka nebo v aktuálních verzích Public Preview.
Návod
Informace o tom, kdy byla funkce poprvé představena v jazyce C#, najdete v článku o historii verzí jazyka C#.
K práci s ukazateli použijte následující operátory:
- Unární
&operátor (adresa): získání adresy proměnné - Unární
*operátor (nepřímý ukazatel): získání proměnné odkazované ukazatelem - Operátory
->(přístup členů) a[](přístup k elementům) - Aritmetické operátory
+,-,++, a-- - Relační operátory
==, ,!=<,>,<=, a>=
Informace o typech ukazatelů naleznete v tématu Typy ukazatelů.
Poznámka:
Jakákoli operace s ukazateli vyžaduje nebezpečný kontext. Kód, který obsahuje nebezpečné bloky, je nutné zkompilovat pomocí možnosti kompilátoru AllowUnsafeBlocks .
Operátor adresy &.
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
Operand operátoru & musí být pevná proměnná.
Pevné proměnné jsou proměnné, které se nacházejí v umístěních úložiště, které uvolňování paměti neovlivní. 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é se nacházejí v umístěních úložiště, můžou mít vliv na uvolňování paměti (například přemístění), se nazývají pohyblivé proměnné. Pole objektů a prvky pole jsou příklady pohyblivých proměnných. Adresu pohyblivé proměnné můžete získat pomocí příkazu "fix" nebo "pin"fixed. 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 najdete v části Pevné a pohyblivé proměnné specifikace jazyka C#.
Binární & operátor vypočítá logický operátor AND logických operandů nebo bitové logické operátory AND integrálních operandů.
Operátor nepřímých ukazatelů *
Operátor * nepřímých ukazatelů unárního ukazatele přistupuje k proměnné, ke které její operand odkazuje. Označuje se také jako operátor dereference. 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 * u výrazu typu void*.
Binární * operátor vypočítá součin číselných operandů.
Operátor přístupu člena ukazatele ->
Operátor -> kombinuje nepřímý ukazatel a přístup členů. 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 -> u výrazu typu void*.
Přístupový operátor prvku ukazatele []
Pro výraz p typu ukazatele je přístup prvku ukazatele formuláře p[n] vyhodnocen jako *(p + n). Hodnota n musí být typu implicitně konvertibilní 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 do nebo z oddílu ukazatele .
Následující příklad ukazuje, jak získat přístup k prvkům pole pomocí ukazatele a operátoru [] :
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ělí blok paměti v zásobníku.
Poznámka:
Přístupový operátor prvku ukazatele nekontroluje chyby mimo hranice.
Nelze použít [] pro přístup k prvkům ukazatele s výrazem typu void*.
Operátor můžete použít [] také pro přístup k prvku pole nebo indexeru.
Aritmetické operátory ukazatele
Pomocí ukazatelů můžete provádět následující aritmetické operace:
- Sčítání nebo odečítání celočíselné hodnoty ukazatelem nebo od ukazatele
- Odečíst dva ukazatele
- Zvýšení nebo snížení ukazatele
Tyto operace nelze provádět pomocí ukazatelů typu void*.
Informace o podporovaných aritmetických operacích pomocí číselných typů najdete v tématu Aritmetické operátory.
Sčítání nebo odečítání celočíselné hodnoty ukazatelem nebo od ukazatele
Pro ukazatel p typu a výraz n typu implicitně konvertibilní na int, uint, long, nebo ulong, sčítání a odčítání T* fungují takto:
- Oba
p + nan + pdát ukazatel typuT*. Tento ukazatel získáte přidánímn * sizeof(T)na adresu, na kteroupodkazuje. - Výraz
p - nvám poskytne ukazatel typuT*. Tento ukazatel získáte odečtenímn * sizeof(T)od adresy, na kteroupodkazuje.
Operátor sizeof získá velikost typu v bajtech.
Následující příklad ukazuje, jak používat + operátor 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
U dvou ukazatelů p1 a p2 typu T*výraz p1 - p2 poskytuje rozdíl mezi adresami, na které a p2 na které p1 odkazuje, děleno .sizeof(T) Výsledek je typu long. Jinými slovy, p1 - p2 vypočítá se 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á 1 do operandu ukazatele. Operátor -- dekrementace odečte 1 od operandu ukazatele.
Oba operátory podporují dvě formy: příponu (p++ a p--) a předponu (++p a --p). Výsledek p++ a p-- je hodnota ppřed operací. Výsledek ++p a --p je hodnota pza operací.
Následující příklad ukazuje chování přípony i operátoru inkrementace předpony:
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ů
K ==!=<><=>= porovnání operandů libovolného typu ukazatele, včetně .void* Tyto operátory porovnávají adresy zadané dvěma operandy, jako by byly 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 Relační operátory .
Priorita operátorů
Následující seznam obsahuje operátory související s ukazateli počínaje nejvyšší prioritou na nejnižší:
- Příponové operátory inkrementace a dekrementace
x++x--a operátory a->operátory[] - Operátory inkrementace a dekrementace
++x--xpředpony a operátory a&operátory* - Sčítání
+a-operátory - Porovnání
<,>,<=a>=operátory - Rovnost
==a!=operátory
Pomocí závorek změňte ()pořadí vyhodnocení uložené podle priority operátoru.
Úplný seznam operátorů jazyka C# seřazených podle úrovně priority najdete v části Priorita operátorů v článku operátory jazyka C#.
Přetížení operátoru
Nelze přetěžovat operátory &související s ukazatelem , *->a [] v uživatelem definovaném typu.
specifikace jazyka C#
Další informace najdete v následujících částech specifikace jazyka C#:
- Pevné a pohyblivé proměnné
- Operátor adresy
- Nepřímý ukazatel
- Přístup ke členu ukazatele
- Přístup k elementu ukazatele
- Aritmetika ukazatele
- Zvýšení a snížení ukazatele
- Porovnání ukazatelů