Інформатика
Область видимості : Час життя та область видимості
 

Час життя та область видимості

     У мові С блоком є послідовність оголошень, визначень і операторів, укладена у фігурні дужки. Існують два види блоків - складений оператор і визначення функції, що складається зі складеного оператора, що є тілом функції, і передує тілу заголовка функції (у який входять ім'я функції, типи значення, що повертається, і формальних параметрів). Блоки можуть містити в собі складені оператори, але не визначення функцій. Внутрішній блок називається вкладеним, а зовнішній блок - осяжним.

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

     Всі функції в С мають глобальний час життя й існують протягом усього часу виконання програми.

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

     Якщо об'єкт оголошений усередині блоку, то він видимий у цьому блоці, і у всіх внутрішніх блоках. Якщо об'єкт оголошений на зовнішньому рівні, то він видимий від точки його оголошення до кінця даного вихідного файлу.

     Об'єкт може бути зроблений глобально видимим за допомогою відповідних оголошень у всіх вихідних файлах, що утворять програму.

     Специфікатор класу пам'яті в оголошенні змінної може бути auto, register, static або extern. Якщо клас пам'яті не зазначений, то він визначається за замовчуванням з контексту оголошення.

     Об'єкти класів auto і register мають локальний час життя. Специфікатори static і extern визначають об'єкти із глобальним часом життя.

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

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

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

     Специфікатор класу пам'яті register пропонує компіляторові розподілити пам'ять для змінної в регістрі, якщо це представляється можливим. Використання регістрової пам'яті звичайно приводить до скорочення часу доступу до змінної. Змінна, оголошена із класом пам'яті register, має ту ж область видимості, що й змінна auto. Число регістрів, які можна використовувати для значень змінних, обмежено можливостями комп'ютера, і в тому випадку, якщо компілятор не має в розпорядженні вільних регістрів, то змінній виділяється пам'ять як для класу auto. Клас пам'яті register може бути зазначений тільки для змінних з типом int або покажчиків з розміром, рівним розміру int.

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

Приклад 1. Оголошення змінної i на внутрішньому рівні с класом пам'яті static. Вихідний файл file1.c.

#include<iostream.h>

void main()

{

     ...

}

fun1()

{

     static int i=0;

      ...

}

/* вихідний файл file2.c */

fun2()

{

     static int i=0;

     ...

}

fun3()

{

     static int i=0;

     ...

}

     У наведеному прикладі оголошені три різні змінні із класом пам'яті static, що мають однакові імена i. Кожна із цих змінних має глобальний час життя, але видима тільки в тім блоці (функції), у якій вона оголошена. Ці змінні можна використовувати для підрахунку числа звертань до кожної із трьох функцій.

     Змінні класу пам'яті static можуть бути ініціалізовані константним вираженням. Якщо явної ініціалізації немає, то такій змінній привласнюється нульове значення. При ініціалізації константним адресним вираженням можна використовувати адреси будь-яких зовнішніх об'єктів, крім адрес об'єктів із класом пам'яті auto, тому що адреса останніх не є константою й змінюється при кожному вході в блок. Ініціалізація виконується один раз при першому вході в блок.

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

Приклад 2. Оголошення змінної i, що є ім'ям зовнішнього масиву довгих цілих чисел, на локальному рівні, вихідний файл file1.cрр.

#include<iostream.h>

void main()

{

     ...

}

fun1()

{

     extern long i[]; ...

}

/* вихідний файл file2.cрр */

long i[MAX]={0};

fun2()

{

     ...

}

fun3()

{

     ...

}

     Оголошення змінної i[] як extern у наведеному прикладі робить її видимої усередині функції fun1. Визначення цієї змінної перебуває у файлі file2.cрр на глобальному рівні й повинне бути тільки одне, у той час як оголошень із класом пам'яті extern може бути кілька.

     Оголошення із класом пам'яті extern потрібно при необхідності використовувати змінну, описану в поточному вихідному файлі, але нижче по тексту програми, тобто до виконання її глобального визначення.

Приклад 3. Використання змінних, описанних в поточному вихідному файлі.

#include<iostream.h>

void main()

{

     extern int st[];

     ...

}

static int st[MAX]={0};

fun1()

{

      ...

}

     Оголошення змінної зі специфікатором extern інформує компілятор про те, що пам'ять для змінної виділяти не потрібно, тому що це виконано десь в іншому місці програми.

     При оголошенні змінних на глобальному рівні може бути використаний специфікатор класу пам'яті static або extern, а так само можна оголошувати змінні без вказівки класу пам'яті. Класи пам'яті auto і register для глобального оголошення неприпустимі.

     Оголошення змінних на глобальному рівні - це або визначення змінних, або посилання на визначення, зроблені в іншому місці програми. Оголошення глобальної змінної, котре ініціалізує цю змінну (явно або неявно), є визначенням змінної. Визначення на глобальному рівні може задаватися в наступних формах.

1. Змінна оголошена із класом пам'яті static. Така змінна може бути ініціалізована явно константним вираженням, або за замовчуванням нульовим значенням. Тобто оголошення static int рi=0; і static int рi; еквівалентні, і в обох випадках змінній рi буде привласнене значення 0.

2. Змінна оголошена без вказівки класу пам'яті, але з явною ініціалізацією. Такій змінній за замовчуванням привласнюється клас пам'яті static. Тобто оголошення int i=1 і static int i=1 будуть еквівалентні.

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

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

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

     В оголошеннях із класом пам'яті extern не допускається ініціалізація, тому що ці оголошення посилаються на вже існуючі й визначені раніше змінні.

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

 
© 2008 ХНУРЭ, Інформатики, Сінельнікова Т.Ф., informatika@kture.Kharkov.ua
Розроблено за допомогою LERSUS