- •Структурування обчислень на рівні підзадач Блочна організація програм Принцип модульності програм
- •Поняття підпрограми
- •Принцип локалізації
- •Концепція розподілу пам’яті
- •Процедурне програмування Організація підпрограм
- •Механізм передачі параметрів
- •Різновиди підпрограм
- •Покажчики та посилання
- •Способи передачі параметрів
- •Рекурсія
- •Стандартні бібліотечні модулі.
- •Бібліотечні модулі користувача
- •Компіляція модулів
Концепція розподілу пам’яті
При активізації програми в оперативній пам’яті ЕОМ створюється її образ, структура якого представлена на рис. 2.
-
16 Кб
Сегмент стека
(росте вниз )
Вільна пам'ять стека
64 Кб
Сегмент даних основної програми (глобальні змінні і
типізовані константи)
64 Кб
Сегмент коду модуля 1
образ
. . .
.exe- файлу
64 Кб
Сегмент коду модуля N
64 Кб
Сегмент коду основної програми
Молодші адреси
Рис. 2 Карта розподілу оперативної пам’яті ПК при активізації програми
Область оперативної пам’яті, що її використовує програма, поділяється на декілька розділів -сегментів.
Сегмент - область оперативної пам’яті (зазвичай об’ємом 64 Кб), що служить для розміщення певного виду інформації.
В сегменті коду програми зберігаються команди програми, в сегменті модулів – коди бібліотечних модулів, в сегменті даних – значення глобальних змінних і типізованих констант. Сегмент стека (за замовчуванням - 16Кб) служить для збереження викликів підпрограм (їх точок повернення), а також локальних змінних. Його особливістю є принцип обробки свого вмісту. У програмному стеці доступним завжди є тільки один елемент – вершина стеку. Елементи стеку обробляються за принципом LIFO (Last Input - First Output) - “останнім прийшов - першим пішов”.
Коли здійснюється виклик підпрограми, відповідна точка повернення в програму запам’ятовується в стеці і зберігається там до завершення роботи цієї підпрограми. Там же розміщуються і її локальні змінні. Після завершення роботи підпрограми стек автоматично очищується, що призводить до знищення розміщених там даних.
При цьому під усі глобальні дані пам'ять виділяється на етапі компіляції (у сегменті даних) і її розмір залишається незмінним протягом всього часу роботи програми.
Процедурне програмування Організація підпрограм
Підпрограми, які використовуватимуться в програмі, повинні бути попередньо визначені (описані). При цьому кожній підпрограмі дається своє ім'я, а також описуються дії, що складають сенс підпрограми. РБНФ визначення підпрограми:
опис підпрограми ::= заголовок; тіло підпрограми.
Заголовок підпрограми містить її ім'я і деяку додаткову інформацію, що уточнює використання цієї підпрограми. Тіло підпрограми є тим програмним фрагментом, який описує виконувані підпрограмою дії.
Зазвичай, структура підпрограми повторює структуру програми, але задані в ній описи вважаються локальними. В розділі локальних даних (який взагалі може бути відсутнім) описують ті дані, які використовуються тільки для «службових» цілей в самій підпрограмі (параметри циклів, робочі змінні, тощо).
Розглянемо наступну задачу: для заданих дійсних значень х і у обчислити
u = mах(х+у, х*у), v = mах(0.5, u).
Програму розв’язання цієї задачі без використання підпрограм можна представити наступним чином:
program Мах_1;
var x,y, {вхідні дані}
u,v:real; {результати обчислень}
begin
ReadLn(x,y);
if x+y > x*y then u:=x+y
else u:=~x*y;
if 0.5>u then v:=0.5
else v:=u;
WrіteLn(' u=',u,' v=',v)
ReadLn
end.
Як видно, в даній програмі фігурують два умовні оператори, кожен з яких призначений для вирішення по суті справи однієї і тієї ж часткової задачі: знаходження більшого з двох заданих дійсних значень і присвоєння деякій змінній отриманого результату. Тому алгоритм розв’язання цієї задачі доцільно оголосити підпрограмою.
Щоб підкреслити схожість двох згаданих вище умовних операторів, запишемо програму трохи інакше:
program Max_2;
var x,y,u,v:real;
a,b,s:real;
begin
ReadLn(x,y);
a:=x+y; b:=x*y;
if a>b then s:=a
else s:=b;
u:=s;
a:=0.5; b:=u;
if a>b then s:=a
else s:=b;
v: =s;
WrіteLn(' u=',u,' v=',v)
ReadLn
end.
У цій програмі умовні оператори в точності збігаються один з одним, тому можна вважати, що один і той же умовний оператор присутній в програмі двічі. Щоб уникнути двократного виписування цього оператора в розділі операторів програми, оголосимо його підпрограмою, якій дамо ім'я Max_РP:
procedure Max_РP;
begin
if а>b then s:=a
else s:=b
end;
Для активації цієї підпрограми в потрібному місці програми достатньо записати там оператор виклику даної підпрограми, що складається лише з її імені, - Max_РP. З використанням такої підпрограми вихідна програма прийме вигляд:
program Max_3;
var x,y,u,v:real;
a,b,s:real;
procedure Max_РP;
begin
if а>b then s:=a
else s:=b
end;
begin
ReadLn(x,y);
a:=x+y; b:=x*y;
Max_PP;
u:=s;
a:=0.5; b:=u;
Max_PP;
v:=s;
WrіteLn(' u=',u,' v=',v)
ReadLn
end.
Оскільки в даному випадку фрагмент тексту програми, оголошений підпрограмою, невеликий, то істотного виграшу у розмірі загального тексту програми ми не отримали. Проте, якби цей фрагмент був чималим, то виграш був би очевидний. Але навіть і в даному випадку основна частина програми — її розділ операторів — стала компактнішою і наочнішою в порівнянні із попереднім варіантом програми (з ім'ям Max_2).