Указатели могут быть организованы в массивы, как и любой другой тип данных. Ниже приведен пример объявления массива указателей типа int
длиной в три элемента.
int * [] ptrs = new int * [3];
Для того чтобы присвоить адрес переменной var типа int
третьему элементу массива указателей, достаточно написать следующую строку кода.
ptrs[2] = &var
А для того чтобы обнаружить значение переменной var, достаточно написать приведенную ниже строку кода.
*ptrs[2]
Во время работы с небезопасным кодом иногда полезно знать размер в байтах одного из встроенных в C# типов значений. Для получения этой информации служит оператор sizeof
. Ниже приведена его общая форма:
sizeof(тип)
где sizeof
предназначен главным образом для особых случаев и, в частности, для работы со смешанным кодом: управляемым и неуправляемым.
Для распределения памяти, выделенной под стек, служит оператор stackalloc
. Им можно пользоваться лишь при инициализации локальных переменных. Ниже приведена общая форма этого оператора:
тип *р = stackalloc тип [размер]
где System.StackOverflowException
. И наконец, оператор stackalloc
можно использовать только в небезопасном коде.
Как правило, память для объектов выделяется из кучи — динамически распределяемой свободной области памяти. А выделение памяти из стека является исключением. Ведь переменные, располагаемые в стеке, не удаляются средствами "сборки мусора", а существуют только в течение времени выполнения метода, в котором они объявляются. После возврата из метода выделенная память освобождается. Преимущество применения оператора stackalloc
заключается, в частности, в том, что в этом случае не нужно беспокоиться об очистке памяти средствами "сборки мусора".
Ниже приведен пример применения оператора stackalloc.
// Продемонстрировать применение оператора stackalloc.
using System;
class UseStackAlloc {
unsafe static void Main() {
int* ptrs = stackalloc int[3];
ptrs[0] = 1;
ptrs[1] = 2;
ptrs[2] = 3;
for(int i=0; i < 3; i++)
Console.WriteLine(ptrs[i]);
}
}
Вот к какому результату приводит выполнение кода из данного примера.
1
2
3
Ключевое слово fixed
находит еще одно применение при создании одномерных массивов фиксированного размера. В документации на C# такие массивы называются
Для создания буфера фиксированного размера служит следующая общая форма:
fixed тип имя_буфера[размер];
где
Для того чтобы стала очевиднее польза от буферов фиксированного размера, рассмотрим ситуацию, в которой программе ведения счетов, написанной на C++, требуется передать информацию о банковском счете. Допустим также, что учетная запись каждого счета организована так, как показано ниже.
Name - Строка длиной 80 байтов, состоящая из 8-разрядных символов в коде ASCII
Balance - Числовое значение типа double длиной 8 байтов
ID - Числовое значение типа long длиной 8 байтов
В программе на C++ каждая структура содержит массив Name, тогда как в программе на C# в такой структуре хранится лишь ссылка на массив. Поэтому для правильного представления данных из этой структуры в C# требуется буфер фиксированного размера, как показано ниже.
// Использовать буфер фиксированного-размера.
unsafe struct FixedBankRecord {