где р обозначает указатель, получающий адрес области памяти, достаточной для хра нения объектов, имеющих указанный тип, в количестве, которое обозначает размер. Если же в стеке недостаточно места для распределения памяти, то генерируется ис ключение 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 { public fixed byte Name[80]; // создать буфер фиксированного размера public double Balance; public long ID; }
Когда буфер фиксированного размера используется вместо массива Name, каждый экземпляр структуры FixedBankRecord будет содержать все 80 байтов массива Name. Именно таким образом структура и организована в программе на C++. Следовательно, общий размер структуры FixedBankRecord окажется равным 96, т.е. сумме ее членов. Ниже приведена программа, демонстрирующая этот факт. // Продемонстрировать применение буфера фиксированного размера. using System; // Создать буфер фиксированного размера. unsafe struct FixedBankRecord { public fixed byte Name[80]; public double Balance; public long ID; } class FixedSizeBuffer { // Пометить метод Main как небезопасный. unsafe static void Main { Console.WriteLine("Размер структуры FixedBankRecord: " + sizeof(FixedBankRecord)); } }
Эта программа дает следующий результат. Размер структуры FixedBankRecord: 96