Новое значение переменной о.num: 10
В данном примере модификатор fixedпрепятствует удалению объекта о. А поскольку переменная руказывает на переменную экземпляра о.num, то она будет указывать на недостоверную область памяти, если удалить объект о.
Доступ к членам структуры с помощью указателя
Указатель может указывать на объект типа структуры при условии, что структура не содержит ссылочные типы данных. Для доступа к члену структуры с помощью указателя следует использовать оператор-стрелку ( ->), а не оператор-точку ( .). Например, доступ к членам структуры
struct MyStruct {
public int a;
public int b;
public int Sum() {
return a + b;
}
}
осуществляется следующим образом.
MyStruct о = new MyStruct();
MyStruct* p; // объявить указатель
p = &o;
p->a = 10; // использовать оператор ->
p->b = 20; // использовать оператор ->
Console.WriteLine("Сумма равна " + p->Sum());
Арифметические операции над указателями
Над указателями можно выполнять только четыре арифметические операции: ++, --, +и -. Для того чтобы стало понятнее, что именно происходит в арифметических операциях над указателями, рассмотрим сначала простой пример. Допустим, что переменная p1является указателем с текущим значением 2000, т.е. она содержит адрес 2000. После выполнения выражения
p1++;
переменная p1 будет содержать значение 2004, а не 2001! Дело в том, что после каждого инкрементирования переменная p1указывает на следующее значение типа int. А поскольку тип intпредставлен в C# 4 байтами, то в результате инкрементирования значение переменной p1увеличивается на 4. Справедливо и обратное: при каждом декрементировании переменной p1ее значение уменьшается на 4. Например выражение
p1--;
приводит к тому, что значение переменной p1становится равным 1996, если раньше оно было равно 2000!
Все сказанное выше можно обобщить: после каждого инкрементирования указатель будет указывать на область памяти, где хранится следующий элемент его соотносимого типа, а после каждого декрементирования указатель будет указывать на область памяти, где хранится предыдущий элемент его соотносимого типа.
Арифметические операции над указателями не ограничиваются только инкрементированием и декрементированием. К указателям можно добавлять и вычитать из них целые значения. Так, после вычисления следующего выражения:
p1 = p1 + 9;
переменная p1будет указывать на девятый элемент ее соотносимого типа по отношению к элементу, на который она указывает в настоящий момент.
Если складывать указатели нельзя, то разрешается вычитать один указатель из другого, при условии, что оба указателя имеют один и тот же соотносимый тип. Результатом такой операции окажется количество элементов соотносимого типа, которые разделяют оба указателя.
Кроме сложения и вычитания целого числа из указателя, а также вычитания двух указателей, другие арифметические операции над указателями не разрешаются. В частности, к указателям нельзя добавлять или вычитать из них значения типа floatили double. Не допускаются также арифметические операции над указателями типа void*.
Для того чтобы проверить на практике результаты арифметических операций над указателями, выполните приведенную ниже короткую программу, где выводятся физические адреса, на которые указывает целочисленный указатель ( ip) и указатель с плавающей точкой одинарной точности ( fp). Понаблюдайте за изменениями каждого из этих указателей по отношению к их соотносимым типам на каждом шаге цикла.
// Продемонстрировать результаты арифметических операций над указателями.
using System;
class PtrArithDemo {
unsafe static void Main() {
int x;
int i;
double d;
int* ip = &i;
double* fp = &d;
Console.WriteLine("int double\n");
for(x=0; x < 10; x++) {
Console.WriteLine((uint) (ip) + " " + (uint) (fp));
ip++;
fp++;
}
}
}
Читать дальше