Оголошення та визначення

Час життя – це проміжок часу існування об'єкта в процесі виконання програми. Він буває глобальним і локальним. Глобальний – коли об'єкт існує протягом усього часу виконання програми. Локальний – коли об'єкт існує на деякому проміжку, що включається до часу виконання програми.

Під областю дії об'єкта розумітимемо частину програми (коду програми), де можливим є використання імені об'єкта. Існують об'єкти, що мають глобальний час життя, але локальну область дії.

Під оголошенням функції розумітимемо конструкцію, у якій задається лише прототип функції та (необов'язково) специфікація класу пам'яті. Наприклад:

float s=5;

float f(float);

s=s+f(1);

У другому рядку лише оголошується функція f, тіло якої визначається в іншому місці програми (напр., нижче за текстом).

Під визначенням змінної розумітимемо конструкцію, обробка якої викликає виділення пам'яті. Наприклад:

int i=0;

Під оголошенням змінної розумітимемо конструкцію, яка є лише посиланням на визначення, зроблені в іншому місці програми (зазвичай в іншому файлі). Наприклад:

int i;

i=4;

//...

{

static int i=5;

}

Розглянемо рядок програми int i; Як його інтерпретувати з погляду оголошення чи визначення змінної i? Це може бути як оголошення, так і визначення. Якщо в програмі більше не зустрічається оголошення чи визначення змінної i, то це буде визначенням. Воно супроводжується виділенням пам'яті та ініціалізацією нулем, якщо цей рядок коду знаходиться на зовнішньому рівні. Якщо в іншому міс­ці програми знаходиться визначення змінної i, то вказана конструк­ція є оголошенням:

Файл1 файл2

int i; int i=5;

Змінна вважається оголошеною на зовнішньому рівні, якщо вона знаходиться в тексті програми за межами функції. Якщо змінна описана всередині функції, то вважається, що вона визначена на внутрішньому рівні. Функція може бути визначена лише на зовнішньому рівні, але оголошена й на внутрішньому:

Main()

{ …

{

float f(int,int);

i++;

…};

};

Змінна, визначена на зовнішньому рівні, має глобальний час життя та область дії від точки визначення до кінця вихідного файла. Вище від точки визначення у файлі змінна недоступна:

…..

Void f(void)

{

i++;

}

int i=5;

Main()

{

i++;

}

У функції f змінна і недоступна. Щоб вона була доступною, необхідно розширити область дії змінної шляхом її оголошення перед функцією f: int i;

Змінна, оголошена на внутрішньому рівні, має локальний час життя та область дії від точки визначення до кінця блоку. За межами блоку, де вона не визначена, змінна недоступна.

Оголошення функції можливе й на внутрішньому рівні. Тоді область дії функції поширюється від точки визначення до кінця файла.

Класи пам'яті

Існує чотири специфікації класів пам'яті:

a register;

a auto;

a static;

a extern.

Специфікатори класу пам'яті можуть впливати на час життя та область дії програмних об'єктів. Специфікатор класу пам'яті register дозволяє розміщувати відповідну змінну (типу int) у регістрах мікропроцесора. Якщо місця там немає, то відповідна специфікація ігнорується і змінна вважається автоматичною, тобто має клас пам'яті auto. Клас пам'яті auto може бути випущеним. Будь-яка змінна вважається автоматичною за умовчанням, локальна змінна записується в стек. Специфікатор класу пам'яті static, що застосовується до зовнішнього об'єкта – змінної чи функції, – обмежує область дії лише вихідним файлом. Відповідний специфікатор може застосовуватись і до внутрішніх об’єктів. Це дає можливість вплинути на час життя відповідної змінної – він стає глобальним. Наприклад:

{

static int i;

}

Статистичні змінні записуються у сегмент даних.

Специфікатор класу пам'яті extern указує компілятору на те, що даний об'єкт є лише посиланням на визначення в іншому місці програми:

Файл1 файл2

extern int i; int i=5;

Зауважимо, що при визначенні змінної допускається її ініціалізація:

TYPE x=вираз;

або

TYPE x; /*опис*/x=вираз; /*обрахування початкового значення*/

Розглянемо фрагмент програми:

#include <stdio.h> extern double sqrt(); /*квадратний корінь*/ double x=1.17; double s12=sqrt(12.0); /*#1*/ double y=x*2.0; /*#2*/ FILE *fp=fopen("out.out","w"); /*#3*/ main(){ double ss=sqrt(25.0)+x; /*#4*/... }

Рядки з мітками #1, #2 і #3 помилкові, адже при ініціалізації статичних даних (а s12, y і fp такими і є, оскільки описані поза тілом деякої функції) вираз має складатися тільки з констант, оскільки він обраховується компілятором. Тому ні використання значень змінних, ні виклики функцій у даному випадку не допустимі (але можна брати адресу змінних).

У рядку #4 ми ініціалізуємо автоматичну змінну ss. Тому вираз для ініціалізації обраховується вже не компілятором, а під час виконання програми, що дає нам право використовувати змінні, виклики функцій і т. п., тобто вирази мови С, без обмежень.

Інформацію про залежність часу життя та області дії від класу пам'яті й рівня оголошення чи визначення наведено в табл. 6.1.

Таблиця 6.1

Рівень Об'єкт СПКП Час життя Область дії
Зовнішній визначення змінної Static глобальний від точки визначення до кінця файла
оголошення змінної Extern глобальний від точки визначення до кінця файла
оголошення чи визначення функції Externчи Static глобальний від точки визначення до кінця файла
Внутрішній оголошення змінної Extern глобальний блок
визначення змінної Static глобальний блок
визначення змінної Auto чи Register локальний блок
оголошення функції Extern чи Static глобальний залишок вихідного файла

Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: