Ссылки

  • docx
  • 06.05.2020
Публикация на сайте для учителей

Публикация педагогических разработок

Бесплатное участие. Свидетельство автора сразу.
Мгновенные 10 документов в портфолио.

0.1. Ссылки
Иконка файла материала 83.docx

0.1. Ссылки

Пусть вы хотите использовать следующий массив:

VAR  a: array[1..200, 1..200] of Integer;

Давайте подсчитаем, сколько байтов в памяти займет этот массив. Одно число типа Integer занимает 2 байта. Получаем  200*200*2 = 80000 байтов. В сегменте данных массив не умещается, значит привычным образом работать с ним нельзя. Использование ссылок позволяет разместить его в куче (по английски - heap), имеющей гораздо больший размер.

Я привел лишь один из доводов в пользу применения ссылок. А поближе познакомимся мы со ссылками на простом примере.  Задача: Вычислить и напечатать y=a+b, где a и b -  целые числа 2 и 3. Вот традиционная программа для решения этой задачи:

VAR  a, b, y  : Integer;
BEGIN
     a:=2; b:=3;
     y:=a+b;
     WriteLn (y)
END.

 А теперь потребуем, чтобы число 2 и результат 5  размещались в куче (впрочем, строго говоря, не обязательно в куче). Вот программа со ссылками:

VAR   b        :     Integer;
          a,y     :    ^Integer;
BEGIN
     New(a); New(y);
     a^ := 2; b:=3;
     y^ := a^ + b;
     WriteLn (y^)
END.

Пояснения: Все, что выше BEGIN, выполняется на этапе компиляции: Строка a,y:^Integer  приказывает отвести в памяти в сегменте данных две ячейки, но не для будущих чисел 2 и 5, а для адресов ячеек из кучи, в которых эти самые 2 и 5 предполагается хранить. Итак, будущие значения a и y - не числа  2 и 5, а адреса ячеек для этих чисел или, по-другому, ссылки на ячейки для этих чисел. Пока же адреса эти не определены.

Все, что ниже BEGIN, выполняется на этапе выполнения программы: При помощи обращений к процедуре New ( New(a) и New(y) ) мы идем дальше и придаем переменным a и y значения конкретных адресов памяти, то есть отводим для будущих чисел 2 и 5 конкретное место в памяти. Таким образом, мы сталкиваемся с новым для нас явлением - место в памяти отводится не на этапе компиляции,  а на этапе выполнения программы. В Паскале имеются средства и освобождать это место на этапе выполнения программы (процедура Dispose, на которой я не буду останавливаться). Называется все это динамическим распределением памяти и сулит выгоды экономным создателям программ, использующим большие объемы разных данных в разные моменты выполнения программы.

Оператор  a^:= 2  идет еще дальше и посылает в ячейку, адрес которой находится в ячейке a, число 2. Обозначается такая ячейка - a^. Если бы мне вздумалось написать a:=2, это бы значило, что я хочу послать в ячейку a адрес равный двум, что вполне возможно, но синтаксически неверно, так как численные значения адресов задаются по-другому.

Смысл следующих двух операторов очевиден.

Подведем итог. Значок ^, поставленный перед типом (например, ^Integer), означает новый ссылочный тип, значения которого обязаны быть адресами переменной (или ссылками на переменную) исходного типа (в нашем случае Integer).

Значок ^, поставленный после переменной ссылочного типа (например, a^), означает переменную, на которую ссылается исходная переменная (в нашем случае исходная переменная a).

 

Вот еще некоторые возможные операции со ссылками (без особых пояснений):

TYPE      D       = array[1..10] of Real;
              DP     = ^D;
              Int      = ^Integer;
VAR        i, j      :    Int;     { i, j - адреса целых чисел}
              m       :    DP;    { m - адрес первой ячейки массива из 10 вещ. чисел}
BEGIN
     New(i);  New(j);  New(m);
     i^:=4;
     j^:=3;
     j:=i;                       {Теперь j и i содержат адреса одного и того же числа - 4}
     WriteLn(j^);            {поэтому будет напечатано число 4}
     m^[9]:=300            {Девятый элемент массива становится равным числу 300}
END.

Вернемся к задаче о размещении большого массива. Поскольку Паскаль вслед за MS-DOS запрещает не только описывать, но также, естественно, и ссылаться на структуру, объемом превышающую 64К, то ссылаться сразу на весь двумерный массив не выйдет и поэтому программа получится непростой:

TYPE      a        =   array[1..200] of Integer;
              ap      =   ^a;
              a2      =   array[1..200] of ap;
VAR        x        :    a2;                   {x - массив из 200 адресов (каждый - ссылка на строку из 200 элементов

                                                      исходного массива)}


BEGIN
     for i:=1 to 200 do New(x[i]);      {Место для массива отведено}
     ............
     x[128]^[35]:=800;                      {Присвоено значение элементу массива}
     .............
END.

В заключение упомяну, что ссылки полезны еще тем, что позволяют организовывать в памяти структуры переменной длины, такие как  списки, деревья и т.п.


 

Скачано с www.znanio.ru