Поделиться через


Типы указателей (Руководство по программированию на C#)

В небезопасном контексте тип может быть типом указателя, типом значения или ссылочным типом. Объявления типа указателя выполняется одним из следующих способов:

type* identifier;
void* identifier; //allowed but not recommended

Любой из указанных ниже типов может быть типом указателя.

Типы указателей не наследуют от объекта и между типами указателей и object не существует преобразований. Кроме того, упаковка-преобразование и распаковка-преобразование не поддерживают указатели. Однако можно выполнять преобразования между различными типами указателей, а также между типами указателей и целочисленными типами.

При объявлении нескольких указателей в одном объявлении знак * указывается только с базовым типом; он не используется в качестве префикса для каждого имени указателя. Например:

int* p1, p2, p3;   // Ok
int *p1, *p2, *p3;   // Invalid in C#

Указатель не может указывать на ссылку или на структуру, содержащую ссылки, поскольку ссылка на объект может быть подвергнута сбору мусора, даже если на нее указывает указатель. Сборщик мусора не отслеживает наличие указателей любых типов, указывающих на объекты.

Значением переменной-указателя типа myType* является адрес переменной типа myType. Ниже приведены примеры объявлений типов указателей.

Пример

Описание

int* p

p — указатель на целое число.

int** p

p — указатель на указатель на целое число.

int*[] p

p — одномерный массив указателей на целые числа.

char* p

p — указатель на тип char.

void* p

p — указатель на неизвестный тип.

Оператор косвенного обращения указателя * можно использовать для доступа к содержимому, на которое указывает переменная-указатель. В качестве примера рассмотрим следующее объявление:

int* myVariable;

Выражение *myVariable обозначает переменную int, находящуюся по адресу, содержащемуся в myVariable.

В разделах Оператор fixed (Справочник по C#) и Преобразования указателей (Руководство по программированию на C#) есть несколько примеров указателей. В следующем примере показана необходимость наличия ключевого слова unsafe и оператора fixed, а также продемонстрирован способ инкрементирования внутреннего указателя. Этот код можно вставить в функцию Main консольного приложения для его запуска. (Не забудьте включить небезопасный код в Конструктор проектов. Для этого в строке меню выберите Проект, Свойства, а затем на вкладке СборкаРазрешить небезопасный код).

// Normal pointer to an object.
int[] a = new int[5] {10, 20, 30, 40, 50};
// Must be in unsafe code to use interior pointers.
unsafe
{
    // Must pin object on heap so that it doesn't move while using interior pointers.
    fixed (int* p = &a[0])
    {
        // p is pinned as well as object, so create another pointer to show incrementing it.
        int* p2 = p;
        Console.WriteLine(*p2);
        // Incrementing p2 bumps the pointer by four bytes due to its type ...
        p2 += 1;
        Console.WriteLine(*p2);
        p2 += 1;
        Console.WriteLine(*p2);
        Console.WriteLine("--------");
        Console.WriteLine(*p);
        // Deferencing p and incrementing changes the value of a[0] ...
        *p += 1;
        Console.WriteLine(*p);
        *p += 1;
        Console.WriteLine(*p);
    }
}

Console.WriteLine("--------");
Console.WriteLine(a[0]);
Console.ReadLine();

// Output:
//10
//20
//30
//--------
//10
//11
//12
//--------
//12

Для указателя типа void* использовать оператор косвенного обращения нельзя. Однако можно использовать приведение для преобразования указателя типа void в любой другой тип и наоборот.

Указатель может иметь значение null. При применении оператора косвенного обращения к указателю со значением null результат зависит от конкретной реализации.

Обратите внимание, что при передаче указателей между методами может возникнуть неопределенное поведение. В примерах указатель возвращается в локальную переменную через параметр Out или Ref либо в виде результата функции. Если указатель был задан в фиксированном блоке, переменная, на которую он указывает, больше не может быть фиксированной.

В следующей таблице перечислены операторы, которые можно использовать для указателей в небезопасном контексте.

Оператор

Применение

*

Косвенное обращение к указателю.

->

Доступ к члену структуры через указатель.

[]

Индексирование указателя.

&

Получение адреса переменной.

++ и --

Увеличение и уменьшение указателей.

+ и -

Арифметические действия с указателем.

==, !=, <, >, <= и >=

Сравнение указателей.

stackalloc

Выделение памяти в стеке.

Оператор fixed

Временная фиксация переменной, чтобы можно было найти ее адрес.

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

Дополнительные сведения см. в Спецификация языка C#. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.

См. также

Ссылки

Небезопасный код и указатели (Руководство по программированию в C#)

Преобразования указателей (Руководство по программированию на C#)

Выражения указателей (Руководство по программированию на C#)

unsafe (Справочник по C#)

Оператор fixed (Справочник по C#)

stackalloc (Справочник по C#)

Упаковка-преобразование и распаковка-преобразование (Руководство по программированию на C#)

Основные понятия

Руководство по программированию на C#

Другие ресурсы

Типы (Справочник по C#)