Тема «Динамические структуры данных»
1. Оперативная и динамическая память
Рассматриваемые до сих пор программы использовали фрагменты памяти, резервированием которых для программы занимался компилятор. Когда в программе объявляются глобальные переменные, то компилятор при компиляции программы определяет требуемое количество байт для хранения значений переменных по их типу. Такие переменные называются статическими:
Программист может обращаться к участкам памяти по именам переменных, значения которых хранятся в них.
Оперативная память ПК представляет собой совокупность ячеек для хранения информации – байтов, каждый из которых имеет собственный номер. Эти номера называются адресами, которые позволяют обращаться к любому байту памяти.
В ПК адреса задаются совокупностью двух шестнадцатиразрядных слов, которые называются сегментом и смещением. Сегмент – это участок памяти, имеющий размер 64 Кбайт. Смещение указывает, сколько байт от начала сегмента необходимо пропустить, чтобы обратиться к нужному адресу.
Максимальный адресуемый участок памяти составляет 1Мбайт (220 байт). На современных компьютерах адресное пространство составляет 4 Гбайт (232 байт).
Однако средства Турбо Паскаля позволяют адресовать пространство в 1Мбайт. Для этого используется 20-разрядный адрес, который получается из двух 16-разрядных адресов сегмента и смещения:
Сегмент |
15 |
14 |
13 |
12 |
11 |
10 |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|
|
|
|
+ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Смещение |
|
|
|
|
15 |
14 |
13 |
12 |
11 |
10 |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
= |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Адрес |
19 |
18 |
17 |
16 |
15 |
14 |
13 |
12 |
11 |
10 |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Все переменные, объявленные в программе, размещаются в одной непрерывной области оперативной памяти, которая называется сегментом данных.
Например, рассмотрим следующую программу:
Var
a : real; {6 байт}
c : char; {1 байт}
d : array [1..10] of integer; {10*2=20 байт}
i : integer; {2 байта}
begin
a := 4.6;
c := ’z’;
for i:=10 downto 1 do
d[i] := i*10;
end.
Рассмотрим сегмент данных программы:
Смещение | |||||||||||||||
0000 |
0001 |
0002 |
0003 |
0004 |
0005 |
0006 |
0007 |
0008 |
0009 |
000A |
000B |
000C |
000D |
000E |
000F |
а |
c |
d[1] |
d[2] |
d[3] |
d[4] |
d[5] | |||||||||
4.6 |
‘z’ |
100 |
90 |
80 |
70 |
60 | |||||||||
0010 |
0011 |
0012 |
0013 |
0014 |
0015 |
0016 |
0017 |
0018 |
0019 |
001A |
001B |
001C |
001D |
001E |
001F |
d[5] |
d[6] |
d[7] |
d[8] |
d[9] |
d[10] |
i |
|
|
| ||||||
|
50 |
40 |
30 |
20 |
10 |
0 |
|
|
|
Использование статических переменных не всегда удобно при решении многих практических задач.
Например, когда речь идет об обработке заранее неизвестного количества однотипных данных. В этом случае выделение памяти для массива, состоящего из большого количества элементов, может быть неэффективным решением. Поскольку память будет зарезервирована для массива, а фактически в программе она не будет использована.
Другая ситуация: размер выделенного массива может быть недостаточно для обработки данных.
При разработке больших программ может получиться ситуация, когда не будет хватать размера сегмента данных для размещения в нем данных.
В Паскале предусмотрена возможность размещения переменных в памяти в процессе выполнения программы. Для таких целей выделена особая область оперативной памяти, которая называется динамической памятью. Переменные, размещаемые в ней, называются динамическими, т.е. в процессе обработки, данные можно размещать и удалять из оперативной памяти.
Многие практические задачи трудно или невозможно решить без использования динамической памяти.
Размер динамической памяти определяется размером всей свободной оперативной памяти на момент загрузки программы в оперативную память.