
- •8. Указатели
- •8.1. Выражения указателей
- •8.1.1. Получение значения переменной указателя
- •8.1.2. Получение адреса переменной
- •Int number;
- •8.1.3. Доступ к члену структуры с использованием указателя
- •8.1.4. Доступ к элементу массива с использованием указателя
- •8.1.5. Операции инкремента и декремента над указателями
- •8.1.6. Арифметические операции над указателями
- •8.1.7. Сравнение указателей
- •8.1.8. Использование указателей для копирования массива байтов
8.1.6. Арифметические операции над указателями
Сложение и вычитание числовых значений и указателей.
Результатом сложения указателя и числа p+n является указатель, являющийся суммой n * sizeof(p) и адреса p.
Результатом вычитания числа из указателя p-n является указатель, полученный вычитанием n * sizeof(p) из адреса p.
Вычитание указателей.
Например, если p1 и p2 являются указателями типа pointer-type*, то результатом выражения p1-p2 будет: ((long)p1 - (long)p2)/sizeof(pointer_type) .
Пример 8.6. Демонстрация вычитания указателей.
// Компилировать с /unsafe
class PointerDifference
{ unsafe static void Main()
{ int* memory = stackalloc int[30];
long difference;
int* p1 = &memory[4];
int* p2 = &memory[10];
difference = p2 - p1;
System.Console.WriteLine("p1 указывает на адрес " +
"{0}, а p2 – на {1}", (long)p1, (long)p2);
System.Console.WriteLine("sizeof(int) = {0}", sizeof(int));
System.Console.WriteLine("Разность p2 - p1 = {0}", difference);
System.Console.ReadLine();
}
}
/* Вывод:
p1 указывает на адрес 64875556, а p2 – на 64875580
sizeof(int) = 4
Разность p2 - p1 = 6
*/
8.1.7. Сравнение указателей
Пример 8.7. Демонстрация сравнения указателей.
// Компилировать с /unsafe
class PointerCompare
{ unsafe static void Main()
{ int x = 234, y = 236;
int* p1 = &x;
int* p2 = &y;
System.Console.WriteLine("p1 указывает на адрес " +
"{0}, а p2 – на {1}", (long)p1, (long)p2);
System.Console.WriteLine("p1 < p2, {0}", p1 < p2);
System.Console.WriteLine("p1 > p2, {0}", p1 > p2);
System.Console.ReadLine();
}
}
/* Вывод:
p1 указывает на адрес 64875716, а p2 – на 64875712
p1 < p2, False
p1 > p2, True
*/
8.1.8. Использование указателей для копирования массива байтов
Пример 8.8. Использование указателей для копирования байтов из одного массива в другой.
// Компилировать с /unsafe
class TestCopy
{ unsafe static void Copy(byte[] source, int sourceOffset,
byte[] target, int targetOffset, int count)
{ // Создание исключения для случая, если любой из массивов
// не проинициализированы, то копирование завершиться не может.
if ((source == null) || (target == null))
throw new System.ArgumentException();
// Создание исключения для случая, если смещение или
// число байтов для копирования отрицательны,
// то копирование завершиться не может.
if ((sourceOffset < 0) || (targetOffset < 0) || (count < 0))
throw new System.ArgumentException();
// Создание исключения для случая, если число байтов
// от смещения до конца массива меньше числа копируемых байтов,
// то копирование завершиться не может.
if ((source.Length - sourceOffset < count) ||
(target.Length - targetOffset < count))
Throw new System.ArgumentException();
// Фиксация положения в памяти объектов источника и назначения,
// чтобы они не были перемещены "сборщиком мусора".
fixed (byte* pSource = source, pTarget = target)
{ // Определение начальных точек копирования
// в массивах источника и назначения.
byte* ps = pSource + sourceOffset;
byte* pt = pTarget + targetOffset;
// Копирование конкретного количества байтов
// из исходного массива в массив назначения.
for (int i = 0; i < count; i++)
{ *pt = *ps;
pt++;
ps++;
}
}
}
static void Main()
{// Создание 2–х массивов одинаковой длины.
int length = 100;
byte[] byteArray1 = new byte[length];
byte[] byteArray2 = new byte[length];
// Заполнение элементов массива byteArray1 с 0–го по 99–й.
for (int i = 0; i < length; ++i) byteArray1[i] = (byte)i;
// Вывод первых 10-ти элементов исходного массива byteArray1.
System.Console.Write("Первые 10 элементов исходного массива: ");
for (int i = 0; i < 10; ++i)
System.Console.Write(byteArray1[i] + " ");
System.Console.WriteLine();
// Копирование содержимого массива byteArray1 в byteArray2.
Copy(byteArray1, 0, byteArray2, 0, length);
System.Console.WriteLine("Копирование всего массива.");
// Вывод первых 10-ти элементов копии (byteArray2)
System.Console.Write("Первые 10 элементов копии: ");
for (int i = 0; i < 10; ++i)
System.Console.Write(byteArray2[i] + " ");
System.Console.WriteLine();
// Копирование содержимого последних 10 элементов массива
// byteArray1 в начало byteArray2. Параметр offset определяет
// откуда начинается копирование в исходном массиве.
int offset = length - 10;
Copy(byteArray1, offset, byteArray2, 0, length - offset);
System.Console.WriteLine("Копирование последних 10 элементов " +
"исходного массива в начало массива назначения.");
// Вывод первых 10-ти элементов копии (byteArray2)
System.Console.Write("Первые 10 элементов копии: ");
for (int i = 0; i < 10; ++i)
System.Console.Write(byteArray2[i] + " ");
System.Console.WriteLine();
System.Console.ReadLine();
}
}
/* Вывод:
Первые 10 элементов исходного массива: 0 1 2 3 4 5 6 7 8 9
Копирование всего массива.
Первые 10 элементов копии: 0 1 2 3 4 5 6 7 8 9
Копирование последних 10 элементов исходного массива в начало
массива назначения.
Первые 10 элементов копии: 90 91 92 93 94 95 96 97 98 99
*/