в переменной ip сохраняется адрес памяти переменной num. Это адрес расположения переменной num в оперативной памяти компьютера. Он не имеет &
можно рассматривать как возврат адреса той переменной, перед которой она указывается. Таким образом, приведенное выше присваивание словами можно описать так: "Переменная ip получает адрес переменной num."
Второй оператор, *
, является дополнением оператора &
. Этот унарный оператор находит значение переменной, расположенной по адресу, на который указывает его операнд. Следовательно, этот оператор обращается к значению переменной, на которую указывает соответствующий указатель. Так, если переменная ip
содержит адрес памяти переменной num
, как показано в предыдущем примере, то в следующей строке кода:
int val = *ip;
в переменной val
сохраняется значение 10 переменной num
, на которую указывает переменная ip
. Операцию *
можно рассматривать как получение значения по адресу. Поэтому приведенный выше оператор присваивания описывается словами следующим образом: "Переменная val
получает значение по адресу, хранящемуся в переменной ip
."
Оператор *
можно использовать также в левой части оператора присваивания. В этом случае он задает значение, на которое указывает соответствующий указатель, как в приведенном ниже примере.
*ip = 100;
В данном примере значение 100 присваивается переменной, на которую указывает переменная ip
, т.е. переменной num
. Поэтому приведенный выше оператор присваивания описывается словами следующим образом: "Разместить значение 100 по адресу, хранящемуся в переменной ip
."
Любой код, в котором используются указатели, должен быть помечен как небезопасный с помощью специального ключевого слова unsafe
. Подобным образом можно пометить конкретные типы данных (например, классы и структуры), члены класса (в том числе методы и операторы) или отдельные кодовые блоки как небезопасные. В качестве примера ниже приведена программа, где указатели используются в методе Main()
, помеченном как небезопасный.
// Продемонстрировать применение указателей и ключевого слова unsafe.
using System;
class UnsafeCode {
// Пометить метод Main() как небезопасный,
unsafe static void Main() {
int count = 99;
int* p; // создать указатель типа int
p = &count // поместить адрес переменной count в переменной р
Console.WriteLine("Исходное значение переменной count: " + *p);
*p = 10; // присвоить значение 10 переменной count,
// на которую указывает переменная р
Console.WriteLine("Новое значение переменной count: " + *p);
}
}
Эта программа дает следующий результат.
Исходное значение переменной count: 99
Новое значение переменной count: 10
В работе с указателями нередко используется модификатор fixed
, который препятствует удалению управляемой переменной средствами "сборки мусора". Потребность в этом возникает, например, в том случае, если указатель обращается к полю в объекте определенного класса. А поскольку указателю ничего не известно о действиях системы "сборки мусора", то он будет указывать не на тот объект, если удалить нужный объект. Ниже приведена общая форма модификатора fixed
:
fixed
// использовать фиксированный объект
}
где fixed
может быть также указано единственное выражение, а не целый кодовый блок. Модификатор fixed
допускается использовать только в коде, помеченном как небезопасный. Кроме того, несколько указателей с модификатором fixed
могут быть объявлены списком через запятую.
Ниже приведен пример применения модификатора fixed
.
// Продемонстрировать применение оператора fixed.
using System;
class Test {
public int num;
public Test(int i) {
num = i;
}
}
class FixedCode {
// Пометить метод Main() как небезопасный,