Добавить в цитаты Настройки чтения

Страница 332 из 502

<b>sizeof(тип)</b>

где тип обозначает тот тип, размер которого требуется получить. Вообще говоря, оператор sizeof предназначен главным образом для особых случаев и, в частности, для работы со смешанным кодом: управляемым и неуправляемым.

Для распределения памяти, выделенной под стек, служит оператор stackalloc. Им можно пользоваться лишь при инициализации локальных переменных. Ниже приведена общая форма этого оператора:

<b>тип *р = stackalloc тип [размер]</b>

где р обозначает указатель, получающий адрес области памяти, достаточной для хранения объектов, имеющих указанный тип, в количестве, которое обозначает размер. Если же в стеке недостаточно места для распределения памяти, то генерируется исключение System.StackOverflowException. И наконец, оператор stackalloc можно использовать только в небезопасном коде.

Как правило, память для объектов выделяется из кучи — динамически распределяемой свободной области памяти. А выделение памяти из стека является исключением. Ведь переменные, располагаемые в стеке, не удаляются средствами "сборки мусора", а существуют только в течение времени выполнения метода, в котором они объявляются. После возврата из метода выделенная память освобождается. Преимущество применения оператора stackalloc заключается, в частности, в том, что в этом случае не нужно беспокоиться об очистке памяти средствами "сборки мусора".

Ниже приведен пример применения оператора stackalloc.

<b>// Продемонстрировать применение оператора stackalloc.</b>

<b>using System;</b>

<b>class UseStackAlloc {</b>

<b>  unsafe static void Main() {</b>

<b>    int* ptrs = stackalloc int[3];</b>

<b>    ptrs[0] = 1;</b>

<b>    ptrs[1] = 2;</b>

<b>    ptrs[2] = 3;</b>

<b>    for(int i=0; i &lt; 3; i++)</b>

<b>      Console.WriteLine(ptrs[i]);</b>

<b>  }</b>

<b>}</b>

Вот к какому результату приводит выполнение кода из данного примера.

<b>1</b>

<b>2</b>

<b>3</b>

Ключевое слово fixed находит еще одно применение при создании одномерных массивов фиксированного размера. В документации на C# такие массивы называются буферами фиксированного размера. Такие буферы всегда являются членами структуры. Они предназначены для создания структуры, в которой содержатся элементы массива, образующие буфер. Когда элемент массива включается в состав структуры, в ней, как правило, хранится лишь ссылка на этот массив. Используя буфер фиксированного размера, в структуре можно разместить весь массив. В итоге получается структура, пригодная в тех случаях, когда важен ее размер, как, например, в многоязыковом программировании, при согласовании данных, созданных вне программы на С#, или же когда требуется неуправляемая структура, содержащая массив. Но буферы фиксированного размера можно использовать только в небезопасном коде.

Для создания буфера фиксированного размера служит следующая общая форма:

<b>fixed тип имя_буфера[размер];</b>

где тип обозначает тип данных массива; имя_буфера — конкретное имя буфера фиксированного размера; размер — количество элементов, образующих буфер. Буферы фиксированного размера могут указываться только в структуре.

Для того чтобы стала очевиднее польза от буферов фиксированного размера, рассмотрим ситуацию, в которой программе ведения счетов, написанной на C++, требуется передать информацию о банковском счете. Допустим также, что учетная запись каждого счета организована так, как показано ниже.

Name - Строка длиной 80 байтов, состоящая из 8-разрядных символов в коде ASCII

Balance - Числовое значение типа double длиной 8 байтов

ID - Числовое значение типа long длиной 8 байтов

В программе на C++ каждая структура содержит массив Name, тогда как в программе на C# в такой структуре хранится лишь ссылка на массив. Поэтому для правильного представления данных из этой структуры в C# требуется буфер фиксированного размера, как показано ниже.

<b>// Использовать буфер фиксированного-размера.</b>

<b>unsafe struct FixedBankRecord {</b>

<b>  public fixed byte Name[80]; // создать буфер фиксированного размера</b>

<b>  public double Balance;</b>

<b>  public long ID;</b>

<b>}</b>

Когда буфер фиксированного размера используется вместо массива Name, каждый экземпляр структуры FixedBankRecord будет содержать все 80 байтов массива Name. Именно таким образом структура и организована в программе на C++. Следовательно, общий размер структуры FixedBankRecord окажется равным 96, т.е. сумме ее членов. Ниже приведена программа, демонстрирующая этот факт.

<b>// Продемонстрировать применение буфера фиксированного размера,</b>

<b>using System;</b>

<b>// Создать буфер фиксированного размера,</b>

<b>unsafe struct FixedBankRecord {</b>

<b>  public fixed byte Name[80];</b>

<b>  public double Balance;</b>

<b>  public long ID;</b>

<b>}</b>

<b>class FixedSizeBuffer {</b>

<b>  // Пометить метод Main() как небезопасный,</b>