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:

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 + n n + p výrazy a vytvoří ukazatel typu T* , který je výsledkem přidání n * sizeof(T) na adresu danou adresou p .
  • p - nVýraz vytvoří ukazatel typu T* , který je výsledkem odečtení n * sizeof(T) od adresy uvedené v p .

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řípony x-- a -> [] operátory a
  • Operátory přírůstku ++x a snížení předpony --x a & * 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#:

Viz také