Указатели р и р2 содержат один и тот же адрес
Как следует из приведенного выше результата, выражения
&nums[0]
И
Nums
оказываются одинаковыми. Но поскольку вторая форма более лаконична, то она чаще используется в программировании, когда требуется указатель на начало массива.
Индексирование указателей
Когда указатель обращается к массиву, его можно индексировать как сам массив. Такой синтаксис служит более удобной в некоторых случаях альтернативой арифметическим операциям над указателями. Рассмотрим следующий пример программы.
// Проиндексировать указатель как массив.
using System;
class PtrlndexDemo {
unsafe static void Main() {
int[] nums = new int[10];
Проиндексировать указатель.
Console.WriteLine("Индексирование указателя как массива.");
fixed (int* p = nums) {
for (int i = 0; i < 10; i++)
p[i] = i; // индексировать указатель как массив
for (int i = 0; i < 10; i++)
Console.WriteLine("p[{0}]: {1} ", i, p[i]);
}
Использовать арифметические операции над указателями.
Console.WriteLine("\nПрименение арифметических " +
"операций над указателями.");
fixed (int* p = nums) {
for (int i = 0; i < 10; i++)
*(p + i) = i; // использовать арифметическую операцию над указателем
for (int i = 0; i < 10; i++)
Console.WriteLine("*(p+{0}): {1} ", i, *(p + i));
}
}
}
Ниже приведен результат выполнения этой программы.
Индексирование указателя как массива.
Р[0] : 0
Р[1] : 1
Р[2] : 2
Р[3] : 3
Р[4] : 4
Р[5] : 5
Р[6] : 6
Р[7] : 7
Р[8] : 8
Р[9] : 9
|
|
Применение арифметических операций над указателями.
*(р+0) : 0
*(P+1) : 1
*(р+2) : 2
*(р+3) : 3
*(р+4) : 4
*(р+5) : 5
*(р+6) : 6
*(р+7) : 7
*(р+8) : 8
*(р+9) : 9
Как следует из результата выполнения приведенной выше программы, общая форма выражения с указателем
*(ptr + i)
может быть заменена следующим синтаксисом индексирования массива.
ptr[i]
Что касается индексирования указателей, то необходимо иметь в виду следующее. Во-первых, при таком индексировании контроль границ массива не осуществляется. Поэтому указатель может обращаться к элементу вне границ массива. И во-вторых, для указателя не предусмотрено свойство Length, определяющее длину массива. Поэтому, если используется указатель, длина массива заранее неизвестна.
Указатели и строки
Символьные строки реализованы в C# в виде объектов. Тем не менее отдельные символы в строке могут быть доступны по указателю. Для этого указателю типа char* присваивается адрес начала символьной строки в следующем операторе с модификатором fixed.
fixed(char* р = str) { // ...
После выполнения оператора с модификатором fixed переменная р будет указывать на начало массива символов, составляющих строку. Этот массив оканчивается символом конца строки, т.е. нулевым символом. Поэтому данное обстоятельство можно использовать для проверки конца массива. В C/C++ строки реализуются в виде массивов, оканчивающихся символом конца строки, а следовательно, получив указатель типа char* на строку, ею можно манипулировать таким же образом, как и в C/C++.
|
|
Ниже приведена программа, демонстрирующая доступ к символьной строке по указателю типа char*.
// Использовать модификатор fixed для получения
// указателя на начало строки.
using System;
class FixedString {
unsafe static void Main() {
string str = "это тест";
Получить указатель р на начало строки str.
fixed(char* p = str) {
Вывести содержимое строки str по указателю р.
for(int i=0; p[i] != 0; i++)
Console.Write(p[i]);
Console.WriteLine();
}
}
}
Эта программа дает следующий результат.
Это тест
Многоуровневая непрямая адресация
Один указатель может указывать на другой, а тот, свою очередь, — на целевое значение. Это так называемая многоуровневая непрямая адресация , или применение указателей на указатели. Такое применение указателей может показаться, на первый взгляд, запутанным. Для прояснения принципа многоуровневой непрямой адресации обратимся за помощью к рис. 20.1. Как видите, значением обычного указателя является адрес переменной, содержащей требуемое значение. Если же применяется указатель на указатель, то первый из них содержит адрес второго, указывающего на переменную, содержащую требуемое значение.
|
|
Многоуровневая непрямая адресация может быть продолжена до любого предела, но потребность более чем в двух уровнях адресации по указателям возникает крайне редко. На самом деле чрезмерная непрямая адресация очень трудно прослеживается и чревата ошибками.
Переменная, являющаяся указателем на указатель, должна быть объявлена как таковая. Для этого достаточно указать дополнительный знак * после имени типа переменной. Например, в следующем объявлении компилятор уведомляется о том, что переменная q является указателем на указатель и относится к типу int.
int** q;
Следует, однако, иметь в виду, что переменная q является указателем не на целое значение, а на указатель типа int.
Для доступа к целевому значению, косвенно адресуемому по указателю на указатель, следует дважды применить оператор *, как в приведенном ниже примере.
using System;
class Multiplelndirect {
unsafe static void Main() {
Дата добавления: 2019-02-12; просмотров: 334; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!