Pointer-gerelateerde operators: neem het adres van variabelen, deductieopslaglocaties en toegang tot geheugenlocaties

Met de aanwijzeroperators kunt u het adres van een variabele (&), deductie van een aanwijzer (*), depointerwaarden vergelijken en aanwijzers en gehele getallen optellen of aftrekken.

U gebruikt de volgende operators om met aanwijzers te werken:

Zie Aanwijzertypen voor meer informatie over aanwijzertypen.

Notitie

Voor elke bewerking met aanwijzers is een onveilige context vereist. De code die onveilige blokken bevat, moet worden gecompileerd met de optie AllowUnsafeBlocks Compiler.

Adres van operator &

De unaire & operator retourneert het adres van de operand:

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

De operand van de & operator moet een vaste variabele zijn. Vaste variabelen zijn variabelen die zich in opslaglocaties bevinden die niet worden beïnvloed door de werking van de garbagecollector. In het voorgaande voorbeeld is de lokale variabele een vaste variabele number , omdat deze zich op de stack bevindt. Variabelen die zich in opslaglocaties bevinden die kunnen worden beïnvloed door de garbagecollector (bijvoorbeeld verplaatst) worden verplaatsbare variabelen genoemd. Objectvelden en matrixelementen zijn voorbeelden van verplaatsbare variabelen. U kunt het adres van een verplaatsbare variabele ophalen als u 'fix' of 'vastmaken' gebruikt, met een fixed instructie. Het verkregen adres is alleen geldig in het blok van een fixed instructie. In het volgende voorbeeld ziet u hoe u een fixed instructie en de & operator gebruikt:

unsafe
{
    byte[] bytes = { 1, 2, 3 };
    fixed (byte* pointerToFirst = &bytes[0])
    {
        // The address stored in pointerToFirst
        // is valid only inside this fixed statement block.
    }
}

U kunt het adres van een constante of een waarde niet ophalen.

Zie de sectie Vaste en verplaatsbare variabelen van de C#-taalspecificatie voor meer informatie over vaste en verplaatsbare variabelen.

De binaire & operator berekent de logische EN van de Booleaanse operanden of de bitsgewijze logische EN van de integrale operanden.

Operator voor aanwijzer indirectie *

De indirectieoperator * unary pointer verkrijgt de variabele waarnaar de operand punten verwijst. Het wordt ook wel de deductieoperator genoemd. De operand van de * operator moet van een type aanwijzer zijn.

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

U kunt de * operator niet toepassen op een expressie van het type void*.

De binaire * operator berekent het product van de numerieke operanden.

Pointer-lidtoegangsoperator ->

De -> operator combineert aanwijzer indirectie en lidtoegang. Dat wil gezegd, als x dit een aanwijzer van het type T* is en y een toegankelijk lid van het type Tis, een expressie van het formulier

x->y

is gelijk aan

(*x).y

In het volgende voorbeeld ziet u het gebruik van de -> operator:

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)
    }
}

U kunt de -> operator niet toepassen op een expressie van het type void*.

Toegangsoperator voor aanwijzerelementen []

Voor een expressie p van een type aanwijzer wordt de toegang tot een aanwijzerelement van het formulier p[n] geëvalueerd als *(p + n), waarbij n een type impliciet moet worden omgezet in int, uint, longof ulong. Zie voor informatie over het gedrag van de + operator met aanwijzers het toevoegen of aftrekken van een integrale waarde naar of van een aanwijzersectie .

In het volgende voorbeeld ziet u hoe u toegang hebt tot matrixelementen met een aanwijzer en de [] operator:

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

In het voorgaande voorbeeld wijst een stackalloc expressie een blok geheugen toe aan de stack.

Notitie

De aanwijzerelementtoegangsoperator controleert niet op fouten buiten de grenzen.

U kunt niet gebruiken [] voor toegang tot aanwijzerelementen met een expressie van het type void*.

U kunt de [] operator ook gebruiken voor toegang tot matrixelementen of indexeerfuncties.

Rekenkundige operatoren voor aanwijzers

U kunt de volgende rekenkundige bewerkingen uitvoeren met aanwijzers:

  • Een integrale waarde aan of van een aanwijzer optellen of aftrekken
  • Twee aanwijzers aftrekken
  • Een aanwijzer verhogen of verlagen

U kunt deze bewerkingen niet uitvoeren met aanwijzers van het type void*.

Zie Rekenkundige operatoren voor informatie over ondersteunde rekenkundige bewerkingen met numerieke typen.

Een integrale waarde van of van een aanwijzer optellen of aftrekken

Voor een aanwijzer p van het type T* en een expressie n van een type impliciet converteerbaar naar int, longuintof , of ulong, worden optellen en aftrekken als volgt gedefinieerd:

  • Zowel p + n als n + p expressies produceren een aanwijzer van het type T* dat het resultaat is van het toevoegen n * sizeof(T) aan het adres dat is opgegeven door p.
  • De p - n expressie produceert een aanwijzer van het type T* dat het resultaat is van het aftrekken n * sizeof(T) van het adres dat is opgegeven door p.

De sizeof operator verkrijgt de grootte van een type in bytes.

In het volgende voorbeeld ziet u het gebruik van de + operator met een aanwijzer:

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

Aftrekken van aanwijzer

Voor twee aanwijzers p1 en p2 van het type T*produceert de expressie p1 - p2 het verschil tussen de adressen die zijn opgegeven door p1 en p2 gedeeld door sizeof(T). Het type van het resultaat is long. Dat wil gezegd, p1 - p2 wordt berekend als ((long)(p1) - (long)(p2)) / sizeof(T).

In het volgende voorbeeld ziet u het aftrekken van de aanwijzer:

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
}

Aanwijzer verhogen en verlagen

De ++ increment-operator voegt 1 toe aan de aanwijzeroperand. De -- operator voor verlagen trekt 1 af van de aanwijzeroperand.

Beide operators worden ondersteund in twee formulieren: postfix (p++ en p--) en voorvoegsel (++p en --p). Het resultaat van p++ en p-- is de waarde van pvóór de bewerking. Het resultaat van ++p en --p is de waarde van pna de bewerking.

In het volgende voorbeeld ziet u het gedrag van incrementele operatoren voor zowel het voorvoegsel als het voorvoegsel:

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

Vergelijkingsoperatoren voor aanwijzers

U kunt de ==operators , !=, <en ><=>= operators gebruiken om operanden van elk type aanwijzer te vergelijken, inclusief void*. Deze operators vergelijken de adressen die door de twee operanden zijn opgegeven alsof ze niet-ondertekende gehele getallen zijn.

Zie de artikelen gelijkheidsoperators en vergelijkingsoperatoren voor informatie over het gedrag van deze operators voor operanden van andere typen.

Operatorprioriteit

De volgende lijst geeft aanwijzers gerelateerde operators vanaf de hoogste prioriteit tot de laagste:

  • Operatoren voor incrementeel x++ en verlagen van x-- postfix en de -> operatoren []
  • Operatoren voor verhogen ++x en verlagen van --x voorvoegsel en de & operatoren *
  • Additief + en - operators
  • Vergelijking<, >, , en >=<=operators
  • Gelijkheid == en != operators

Gebruik haakjes, ()om de volgorde van evaluatie te wijzigen die wordt opgelegd door de prioriteit van de operator.

Zie de sectie Operatorprioriteit van het artikel C#-operators voor de volledige lijst met C#-operators die zijn gerangschikt op prioriteitsniveau.

Overbelasting van operatoren

Een door de gebruiker gedefinieerd type kan de aanwijzer gerelateerde operators &, *en ->.[]

C#-taalspecificatie

Zie de volgende secties van de C#-taalspecificatie voor meer informatie:

Zie ook