Sdílet prostřednictvím


Operátory související s ukazateli – přebírají adresu proměnných, umístění úložiště dereference a přístup k umístěním paměti.

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.

K práci s ukazateli použijte následující operátory:

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, musí být zkompilován s možností 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é nejsou ovlivněné 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é se nacházejí v umístěních úložiště, které mohou být ovlivněny uvolňováním paměti (například přemístěním), 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, pokud ji "opravíte" nebo "připnete", pomocí fixed příkazu. 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 získá proměnnou, na kterou má operand body. 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ů.

Přístupový operátor člena ukazatele –>

Operátor -> kombinuje nepřímý ukazatel a přístup členů. To znamená, že pokud x je ukazatel typu T* a y je přístupný člen 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), kde n musí být typu implicitně konvertibilní na int, uint, longnebo 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 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ě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 s číselnými typy najdete v tématu Aritmetické operátory.

Sčítání nebo odčítání celočíselné hodnoty ukazatele 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í jsou T* definovány takto:

  • Výrazy p + n generují ukazatel typuT*, který je výsledkem přidání n * sizeof(T) na adresu danou pn + p adresou .
  • Výraz p - n vytvoří ukazatel typuT*, který je výsledkem odečtení n * sizeof(T) od adresy zadané .p

Operátor sizeof 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 T*výraz p1 - p2 vytvoří rozdíl mezi adresami zadanými p1 a p2 dělenou .sizeof(T) Typ výsledku je long. To znamená, p1 - p2 že se vypočítá 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 jsou podporovány ve dvou formách: příponu (p++ a p--) a předponu (++p a --p). Výsledek p++ a p-- je hodnota p před operací. Výsledek ++p a --p je hodnota p za 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 --x př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

Uživatelem definovaný typ nemůže přetížit operátory &související s ukazatelem , *, ->, a [].

specifikace jazyka C#

Další informace najdete v následujících částech specifikace jazyka C#:

Viz také