Операторы, связанные с указателем (справочник по C#)Pointer related operators (C# reference)

Для работы с указателями можно использовать следующие операторы:You can use the following operators to work with pointers:

Сведения о типах указателей см. в разделе Типы указателей.For information about pointer types, see Pointer types.

Примечание

Для всех операций с указателями требуется небезопасный контекст.Any operation with pointers requires an unsafe context. Код, содержащий небезопасные блоки, должен компилироваться с параметром компилятора -unsafe.The code that contains unsafe blocks must be compiled with the -unsafe compiler option.

Оператор address-of &Address-of operator &

Унарный оператор & возвращает адрес своего операнда:The unary & operator returns the address of its 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

Операнд оператора & должен быть фиксированной переменной.The operand of the & operator must be a fixed variable. Фиксированные переменные — это переменные в местах хранения, на которые не распространяется сборка мусора.Fixed variables are variables that reside in storage locations that are unaffected by operation of the garbage collector. В приведенном выше примере локальная переменная number — это фиксированная переменная, так как она находится в стеке.In the preceding example, the local variable number is a fixed variable, because it resides on the stack. Переменные, которые находятся в местах хранения, обслуживаемых сборщиком мусора (например, перемещение), называются перемещаемыми переменными.Variables that reside in storage locations that can be affected by the garbage collector (for example, relocated) are called movable variables. Поля объекта и элементы массива являются примерами перемещаемых переменных.Object fields and array elements are examples of movable variables. Вы можете получить адрес перемещаемой переменной, если зафиксируете или закрепите ее с помощью инструкции fixed.You can get the address of a movable variable if you "fix", or "pin", it with a fixed statement. Полученный адрес действителен только в пределах блока инструкции fixed.The obtained address is valid only inside the block of a fixed statement. В следующем примере показано, как использовать инструкцию fixed и оператор &:The following example shows how to use a fixed statement and the & operator:

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

Получить адрес константы или значения нельзя.You can't get the address of a constant or a value.

Дополнительные сведения о фиксированных и перемещаемых переменных см. в разделе Фиксированные и перемещаемые переменные в спецификации языка C#.For more information about fixed and movable variables, see the Fixed and moveable variables section of the C# language specification.

Бинарный оператор & вычисляет логическое И своих логических операндов или побитовое логическое И своих целочисленных операндов.The binary & operator computes the logical AND of its Boolean operands or the bitwise logical AND of its integral operands.

Оператор косвенного обращения указателя *Pointer indirection operator *

Унарный оператор косвенного обращения указателя * получает переменную, на которую указывает операнд.The unary pointer indirection operator * obtains the variable to which its operand points. Он также называется оператором разыменования.It's also known as the dereference operator. Операнд оператора * должен иметь тип указателя.The operand of the * operator must be of a pointer type.

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

Невозможно применить оператор * к выражению типа void*.You cannot apply the * operator to an expression of type void*.

Бинарный оператор * вычисляет продукт своих числовых операндов.The binary * operator computes the product of its numeric operands.

Оператор доступа к члену указателя ->Pointer member access operator ->

Оператор -> объединяет косвенное обращение к указателю и доступ к члену.The -> operator combines pointer indirection and member access. То есть если x — это указатель типа T*, а y является доступным членом типа T, выражение формыThat is, if x is a pointer of type T* and y is an accessible member of type T, an expression of the form

x->y

эквивалентноis equivalent to

(*x).y

В следующем примере иллюстрируется использование оператора ->.The following example demonstrates the usage of the -> 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)
    }
}

Невозможно применить оператор -> к выражению типа void*.You cannot apply the -> operator to an expression of type void*.

Оператор доступа к элементу указателя []Pointer element access operator []

Для выражения p типа указателя доступ к элементу указателя формы p[n] вычисляется как *(p + n), где n должен иметь тип, неявно преобразуемый в int, uint, long или ulong.For an expression p of a pointer type, a pointer element access of the form p[n] is evaluated as *(p + n), where n must be of a type implicitly convertible to int, uint, long, or ulong. Сведения о поведении оператора + с указателями см. в разделе Сложение целочисленного значения с указателем или его вычитание из указателя.For information about the behavior of the + operator with pointers, see the Addition or subtraction of an integral value to or from a pointer section.

Следующий пример демонстрирует доступ к элементам массива с указателем и оператором []:The following example demonstrates how to access array elements with a pointer and the [] 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

В предыдущем примере выражение stackalloc выделяет блок памяти в стеке.In the preceding example, a stackalloc expression allocates a block of memory on the stack.

Примечание

Оператор доступа к элементу указателя не проверяет ошибки за пределами области.The pointer element access operator doesn't check for out-of-bounds errors.

Нельзя использовать [] для доступа к элементу указателя с помощью выражения типа void*.You cannot use [] for pointer element access with an expression of type void*.

Можно также использовать оператор [] для доступа к элементу массива или индексатору.You can also use the [] operator for array element or indexer access.

Арифметические операторы указателяPointer arithmetic operators

Вы можете выполнить следующие арифметические операции с указателями:You can perform the following arithmetic operations with pointers:

  • Сложение целочисленного значения с указателем или его вычитание из указателяAdd or subtract an integral value to or from a pointer
  • Вычитание двух указателейSubtract two pointers
  • Инкремент или декремент указателяIncrement or decrement a pointer

Невозможно выполнить эти операции с указателями типа void*.You cannot perform those operations with pointers of type void*.

Сведения о поддерживаемых арифметических операциях с числовыми типами см. в разделе Арифметические операторы.For information about supported arithmetic operations with numeric types, see Arithmetic operators.

Сложение целочисленного значения с указателем или его вычитание из указателяAddition or subtraction of an integral value to or from a pointer

Для указателя p типа T* и выражения n типа, неявно преобразуемого в int, uint, long или ulong, сложение и вычитание определяются следующим образом:For a pointer p of type T* and an expression n of a type implicitly convertible to int, uint, long, or ulong, addition and subtraction are defined as follows:

  • Выражения p + n и n + p создают указатель типа T*, полученный добавлением n * sizeof(T) к адресу, предоставленному p.Both p + n and n + p expressions produce a pointer of type T* that results from adding n * sizeof(T) to the address given by p.
  • Выражение p - n создает указатель типа T*, полученный вычитанием n * sizeof(T) из адреса, предоставленного p.The p - n expression produces a pointer of type T* that results from subtracting n * sizeof(T) from the address given by p.

Оператор sizeof получает размер типа в байтах.The sizeof operator obtains the size of a type in bytes.

В следующем примере показано использование оператора + с указателем:The following example demonstrates the usage of the + operator with a pointer:

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

Вычитание указателейPointer subtraction

Для двух указателей p1 и p2 типа T* выражение p1 - p2 находит разность между адресами, предоставленными p1 и p2, деленную на sizeof(T).For two pointers p1 and p2 of type T*, the expression p1 - p2 produces the difference between the addresses given by p1 and p2 divided by sizeof(T). Результат имеет тип long.The type of the result is long. То есть p1 - p2 вычисляется как ((long)(p1) - (long)(p2)) / sizeof(T).That is, p1 - p2 is computed as ((long)(p1) - (long)(p2)) / sizeof(T).

В следующем примере показано вычитание указателей:The following example demonstrates the pointer subtraction:

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
}

Инкремент и декремент указателяPointer increment and decrement

Оператор инкремента ++добавляет 1 к своему операнду указателя.The ++ increment operator adds 1 to its pointer operand. Оператор декремента --вычитает 1 из своего операнда указателя.The -- decrement operator subtracts 1 from its pointer operand.

Оба оператора поддерживаются в двух формах: постфикс (p++ и p--) и префикс (++p и --p).Both operators are supported in two forms: postfix (p++ and p--) and prefix (++p and --p). Результат p++ и p-- — это значение p перед операцией.The result of p++ and p-- is the value of p before the operation. Результат ++p и --p — это значение p после операции.The result of ++p and --p is the value of p after the operation.

В следующем примере показано поведение постфиксных и префиксных операторов инкремента:The following example demonstrates the behavior of both postfix and prefix increment operators:

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

Операторы сравнения указателейPointer comparison operators

Вы можете использовать операторы ==, !=, <, >, <= и >= для сравнения операндов любого типа указателя, включая void*.You can use the ==, !=, <, >, <=, and >= operators to compare operands of any pointer type, including void*. Эти операторы сравнивают адреса, предоставленные двумя операндами, как если бы они были целыми числами без знака.Those operators compare the addresses given by the two operands as if they were unsigned integers.

Сведения о поведении этих операторов для операндов других типов см. в статьях Операторы равенства и Операторы сравнения.For information about the behavior of those operators for operands of other types, see the Equality operators and Comparison operators articles.

Приоритет операторовOperator precedence

В следующем списке операторы, связанные с указателями, упорядочены от самого высокого до самого низкого приоритета:The following list orders pointer related operators starting from the highest precedence to the lowest:

  • Постфиксные операторы инкремента x++ и декремента x-- и операторы -> и []Postfix increment x++ and decrement x-- operators and the -> and [] operators
  • Префиксные операторы инкремента ++x и декремента --x и операторы & и *Prefix increment ++x and decrement --x operators and the & and * operators
  • Аддитивные операторы + и -Additive + and - operators
  • Операторы сравнения <, >, <= и >=Comparison <, >, <=, and >= operators
  • Операторы равенства == и !=Equality == and != operators

Используйте скобки (), чтобы изменить порядок вычисления, накладываемый приоритетом операторов.Use parentheses, (), to change the order of evaluation imposed by operator precedence.

Полный список операторов C#, упорядоченный по уровню приоритета, можно найти в разделе Приоритет операторов статьи Операторы C#.For the complete list of C# operators ordered by precedence level, see the Operator precedence section of the C# operators article.

Возможность перегрузки оператораOperator overloadability

Определяемый пользователем тип не может перегружать операторы, связанные с указателем, &, *, -> и [].A user-defined type cannot overload the pointer related operators &, *, ->, and [].

Спецификация языка C#C# language specification

Дополнительные сведения см. в следующих разделах статьи Спецификация языка C#:For more information, see the following sections of the C# language specification:

См. такжеSee also