Dela via


Pekarrelaterade operatorer – ta adressen till variabler, dereferencelagringsplatser och komma åt minnesplatser

Med pekaroperatorerna kan du ta adressen till en variabel (&), dereferera en pekare (*), jämföra pekarvärden och lägga till eller subtrahera pekare och heltal.

Du använder följande operatorer för att arbeta med pekare:

Information om pekartyper finns i Pekartyper.

Kommentar

Alla åtgärder med pekare kräver en osäker kontext. Koden som innehåller osäkra block måste kompileras med kompileringsalternativet AllowUnsafeBlocks .

Adress för operatorn &

Den unary & operatorn returnerar adressen för dess 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

Operatorns & operande måste vara en fast variabel. Fasta variabler är variabler som finns på lagringsplatser som inte påverkas av driften av skräpinsamlaren. I föregående exempel är den lokala variabeln number en fast variabel eftersom den finns i stacken. Variabler som finns på lagringsplatser som kan påverkas av skräpinsamlaren (till exempel flyttade) kallas flyttbara variabler. Objektfält och matriselement är exempel på rörliga variabler. Du kan hämta adressen till en flyttbar variabel om du "korrigerar" eller "fäster", den med en fixed instruktion. Den erhållna adressen är endast giltig i blocket för en fixed -instruktion. I följande exempel visas hur du använder en fixed -instruktion och operatorn & :

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

Du kan inte hämta adressen till en konstant eller ett värde.

Mer information om fasta och rörliga variabler finns i avsnittet Fasta och flyttbara variabler i C#-språkspecifikationen.

Den binära & operatorn beräknar det logiska OCH för dess booleska operander eller den bitvis logiska AND för dess integrerade operander.

Indirekta pekaroperatorer *

Den unary pekare indirection operatorn * hämtar variabeln som dess operand pekar till. Det kallas även för dereferenceoperatorn. Operatorns * operand måste vara av pekartyp.

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

Du kan inte tillämpa operatorn på * ett uttryck av typen void*.

Den binära * operatorn beräknar produkten av dess numeriska operander.

Pekarens medlemsåtkomstoperator –>

Operatorn -> kombinerar indirekt pekare och medlemsåtkomst. x Om är en pekare av typen T* och y är en tillgänglig medlem av typen T, ett uttryck för formuläret

x->y

motsvarar

(*x).y

I följande exempel visas hur operatorn -> används:

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

Du kan inte tillämpa operatorn på -> ett uttryck av typen void*.

Åtkomstoperator för pekarelement []

För ett uttryck p av en pekartyp utvärderas en pekarelementåtkomst för formuläret p[n] som *(p + n), där n måste vara av en typ implicit konvertibel till int, uint, longeller ulong. Information om operatorns + beteende med pekare finns i avsnittet Addition eller subtraktion av ett integralvärde till eller från en pekare .

I följande exempel visas hur du kommer åt matriselement med en pekare och operatorn [] :

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

I föregående exempel allokerar ett stackalloc uttryck ett minnesblock i stacken.

Kommentar

Åtkomstoperatorn för pekarelementet söker inte efter fel utanför gränserna.

Du kan inte använda [] för åtkomst till pekarelement med ett uttryck av typen void*.

Du kan också använda operatorn [] för matriselement eller indexerareåtkomst.

Pekarens aritmetiska operatorer

Du kan utföra följande aritmetiska åtgärder med pekare:

  • Lägga till eller subtrahera ett integralvärde till eller från en pekare
  • Subtrahera två pekare
  • Öka eller minska en pekare

Du kan inte utföra dessa åtgärder med pekare av typen void*.

Information om aritmetiska åtgärder som stöds med numeriska typer finns i Aritmetiska operatorer.

Tillägg eller subtraktion av ett integralvärde till eller från en pekare

För en pekare p av typen T* och ett uttryck n av en typ som implicit kan konverteras till int, uint, longeller ulong, definieras addition och subtraktion på följande sätt:

  • Både p + n och n + p uttryck ger en pekare av typen T* som resulterar från att lägga n * sizeof(T) till adressen som anges av p.
  • Uttrycket p - n genererar en pekare av typen T* som är resultatet av att subtrahera n * sizeof(T) från den adress som anges av p.

Operatorn sizeof hämtar storleken på en typ i byte.

I följande exempel visas användningen av operatorn + med en pekare:

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

Pekarundertraktion

För två pekare p1 och p2 av typen T*ger uttrycket p1 - p2 skillnaden mellan de adresser som anges av p1 och p2 divideras med sizeof(T). Resultatets typ är long. Det vill: p1 - p2 beräknas som ((long)(p1) - (long)(p2)) / sizeof(T).

I följande exempel visas pekarens subtraktion:

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
}

Ökning och minskning av pekare

Inkrementsoperatorn ++ lägger till 1 i pekaroperatorn. Decrementoperatorn -- subtraherar 1 från dess pekaroperator.

Båda operatorerna stöds i två former: postfix (p++ och p--) och prefix (++p och --p). Resultatet av p++ och p-- är värdet p för före åtgärden. Resultatet av ++p och --p är värdet p för efter åtgärden.

I följande exempel visas beteendet för både postfix- och prefixökningsoperatorer:

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

Jämförelseoperatorer för pekare

Du kan använda operatorerna ==, !=, <, >, <=och >= för att jämföra operander av valfri pekartyp, inklusive void*. Dessa operatorer jämför de adresser som anges av de två operanderna som om de vore osignerade heltal.

Information om beteendet för operatorerna för operander av andra typer finns i artiklarna Likhetsoperatorer och Jämförelseoperatorer .

Prioritet för operator

Följande listordningspekare relaterade operatorer från den högsta prioriteten till den lägsta:

  • Postfix-inkrementsx++- och deskrementsoperatorer x-- samt operatorerna -> och []
  • Prefixets inkrements++x- och deskrementsoperatorer --x och operatorerna & och *
  • Additiva + och - operatorer
  • Jämförelse <, >, <=och >= operatorer
  • Likhet == och != operatorer

Använd parenteser, (), för att ändra ordningen på utvärderingen som har införts av operatorprioriteten.

En fullständig lista över C#-operatorer ordnade efter prioritetsnivå finns i avsnittet Operatorprioriteten i artikeln C#-operatorer .

Överlagring av operator

En användardefinierad typ kan inte överbelasta pekarrelaterade operatorer &, *, ->och [].

Språkspecifikation för C#

Mer information finns i följande avsnitt i C#-språkspecifikationen:

Se även