Програмне середовище
Від складання програмістом до виконання комп'ютером програма проходить досить тривалий шлях спеціальними службовими програмами, що складають систему автоматизації програмування. З часом слово “автоматизація” випало із наведеного словосполучення, в результаті чого воно перетворилося на систему програмування. Система програмування складається з кількох компонент, а саме: препроцесора (preprocessor), компілятора (compiler), компонувальника (linker), налагоджувача (debugger) , об'єднаних спільним інтерфейсом у так зване універсальне середовище розробки програм. Прикладом можуть служити система програмування Visual
C++ і діалогове середовище розробки програм Developer Studio.
Головна особливість підготовки програми до виконання полягає у використанні багатьох різнорідних складових частин. Деякі з них підготовлені заздалегідь, вони зберігаються в бібліотеках, системних або власних, інші складають частини програми, розміщені в різних файлах. Зауважимо, що в С++ лише поглибилася тенденція винесення значної частини мови на рівень бібліотеки, яка дула закладена ще авторами С. Зокрема на бібліотеку, а не мову покладена відповідальність за зв'язок програми з операційною системою.
Одночасне використання багатьох файлів з текстами різних частин програми — роздільна компіляція — одне з найбільших досягнень систем програмування. Завдяки йому ми ділимо програму на файли, які називаються одиницями трансляції ( translation
unit ), групуючи у одному файлі тісно зв'язані одну з одною частини програми. В такий спосіб великі за розмірами програми діляться на частини, якими легше управляти.
Програмування — це діяльність, яка вимагає великої організованості. Тому при складанні програм дотримуються певних правил доброго тону, одне з яких полягає в розділенні визначень і обчислень між файлами двох типів: файлів заголовків (header) і файлів реалізації . Файли заголовків обробляються препроцесором, файли реалізації готуються препроцесором для подальшої обробки компілятором. Тому їх звичайно називають початковими файлами ( source
file, исходный файл ). Сукупність пов'язаних одне з одним заголовних і початкових файлів складають вхідну програму для системи програмування. Вхідну програму розміщують у програмному проекті, в рамках якого система програмування будуватиме об'єктні коди та виконавчу програму .
Ми розглядаємо систему програмування тільки тією мірою, якою вона впливає на написання та організацію текстів вхідних програм. За детальним знайомством з засобами і можливостями системи програмування відсилаємо до системної документації і спеціальної літератури.
Система програмування працює з програмними проектами . В проекті розміщують файли вхідної програми. Розглянемо, наприклад, проект sgrt
. До файлу root.cpp ми запишемо текст функції root . Програмний код для випробування цієї функції ми помістимо у файл main.cpp
. Проект, заповнений вхідними файлами, зображено на малюнку
![]() |
![]() |
Пам'ятаємо, що компіляція цих двох файлів виконуватиметься нарізно. Виникає питання, звідки компілятор зрозуміє зміст ідентифікатора root
? В принципі можливі два рішення. Перше — це помістити сам файл root.cpp до файлу main.cpp
, де він використовується. Це було б не дуже вдале рішення, бо незрозуміло, як поступати у випадку одночасного використання у багатьох файлах. Друге рішення, саме воно прийняте в системах програмування, полягає у створенні допоміжного заголовного файлу root.h
, який міститиме не всю інформацію про функцію root , а лише ту, яка необхідна для обробки її виклику компілятором, так звану сигтатуру функції:
//root.h
double root (double x, double eps);
Вказівки препроцесору записуються за допомогою спеціальних директив, запис
яких починається символом #. Зокрема файл main.cpp міститиме директиву #include
?root.h? , виконання якої препроцесором полягає у включенні тексту з файлу
заголовку root.h до початкового файлу main.cpp . Наведемо його текст
//main.cpp
//Спочатку системні заголовки
#include "stdafx.h"
#include <iostream>
#include <сmath>
using namespace std;
#include "root.h"
int main()
{
cout << "The square root of 2 calculated with"<<endl
<<" a standart fuction is "<<sqrt(2.0)<<endl;
cout <<" your function is "<< root(2.0,0.000001)<<endl;
return 0;
}
Як бачимо, початковий файл містить ще декілька файлів, що приєднаються препроцесором.
Це службові файли (вони не зображені на малюнку). Файл stdafx.h генерується
системою програмування Visual C ++ ( ми не будемо більше наводити цю директиву
в наступних прикладах). Два інші описують стандартні бібліотеки: бібліотеку
вводу і виводу iostream (вона потрібна для обслуговування вихідного потоку
cout) та бібліотеку математичних функцій cm ath , звідки береться, наприклад,
функція обчислення квадратного кореня sqrt . Директива using namespace std
є вказівкою компілятору вживати стандартні імена для системних об'єктів, наприклад,
через cout позначено стандартний вихідний потік.
Відповідного доповнення вимагатиме також файл root.cpp , в якому вжито стандартну
функцію fabs обчислення абсолютної величини дійсного числа
//root.cpp
#include <сmath>
double root (double x, double eps)
{
double s=0.5*x;
double t;
do
{
t=s;
s=(s+x/s)*0.5;
}
while ((fabs(s-t)/s)>eps);
return s;
};
Тепер коротко про призначення інших компонент системи програмування. Після
того, що будуть проінтепретовані команди препроцесора, файли повних текстів
потраплять на вхід компілятора, який збере з них так звані об'єктні коди. Компілятор
— центральна компонента системи програмування, мета якого полягає у створенні
цільового (англійською мовою object ) коду. Об'єктний код ще не призначено
для безпосереднього виконання. В проекті їх багато, взагалі кажучи, по одному
на кожен початковий файл. Об'єктні коди містять взаємні посилання один на одного,
а також посилання на бібліотеки. Об'єктні коди поступають на вхід компонувальника.
Його завдання зібрати їх разом, доповнити необхідними компонентами бібліотек
та перетворити на виконавчу програму ( executable program , exe
- file ).
На замовлення компілятор може доповнити об'єктні коди спеціальними командами
спостереження за ходом виконання програми. Тоді виконанням програми займеться
налагоджувач, який дозволить прослідкувати за перебігом виконання: призупинити
виконання програми, проконтролювати значення змінних, тощо.