русс | укр

Мови програмуванняВідео уроки php mysqlПаскальСіАсемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование


Linux Unix Алгоритмічні мови Архітектура мікроконтролерів Введення в розробку розподілених інформаційних систем Дискретна математика Інформаційне обслуговування користувачів Інформація та моделювання в управлінні виробництвом Комп'ютерна графіка Лекції


Зовнішні змінні й область дії


Дата додавання: 2014-11-28; переглядів: 944.


Змінні в main, такі як line, longest тощо, являються приватними або локальними для main. Оскільки їх оголошено всередині main, жодна інша функція не може мати безпосереднього доступу до них. Те саме стосується змінних в інших функціях; наприклад, змінна i функціїgetline не має жодного стосунку до i з copy. Кожна локальна змінна у функції починає існувати тільки тоді, коли викликано функцію і зникає, коли функція закінчила своє виконання. Ось чому такі змінні часто називають автоматичними змінними, наслідуючи термінологію інших мов. Ми теж надалі використовуватимемо цей термін стосовно локальних змінних. (У Розділі 4обговорюється клас зберігання static, в якому локальні змінні утримують своє значення між викликами функцій.)

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

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

Зовнішню змінну треба означити один тільки раз за межами будь-якої функції; це відведе місце для їхнього зберігання. Змінну також потрібно оголосити у кожній функції, яка хоче мати доступ до неї; це заявить про тип змінної. Оголошення може бути явним твердженням extern, або неявним через контекст. Щоб конкретизувати нашу дискусію, перепишімо програму виявлення найдовшого рядка, із line, longest і max, як зовнішні змінні. Це вимагає зміну викликів, оголошень і тіл усіх трьох функцій.

#include <stdio.h>

 

#define MAXLINE 1000 /* максимальна довжина рядка вводу */

 

int max; /* найбільша знайдена довжина */

char line[MAXLINE]; /* поточний введений рядок */

char longest[MAXLINE]; /* зберігає найдовший рядок */

 

int getline(void);

void copy(void);

 

/* виводить найдовший рядок вводу; спеціальна версія */

main()

{

int len;

extern int max;

extern char longest[];

 

max = 0;

while ((len = getline()) > 0)

if (len > max) {

max = len;

copy();

}

if (max > 0) /* було введено рядок */

printf("%s", longest);

return 0;

}

 

/* getline: спеціальна версія */

int getline(void)

{

int c, i;

extern char line[];

 

for (i = 0; i < MAXLINE - 1

&& (c=getchar)) != EOF && c != '\n'; ++i)

line[i] = c;

if (c == '\n') {

line[i] = c;

++i;

}

line[i] = '\0';

return i;

}

/* copy: спеціальна версія */

void copy(void)

{

int i;

extern char line[], longest[];

 

i = 0;

while ((longest[i] = line[i]) != '\0')

++i;

}

Зовнішні змінні в main, getline та copy означено в перших рядках у прикладі вище, що вказує на їхній тип і відводить місце для зберігання. Синтаксично, зовнішні означення схожі на означення локальних змінних, але оскільки це відбувається за межами функцій, змінні стають зовнішніми. Перед тим, як якась функція може користуватися зовнішньою змінною, назва змінної повинна стати відомою функції; оголошення будуть таким самим як дотепер, за винятком доданого слова extern.

В деяких випадках, оголошення extern можна опустити. Якщо означення зовнішньої змінної відбувається у вихідному файлі перед її використанням в якійсь функції, тоді відпадає потреба в оголошенні extern всередині функції. Таким чином, оголошення extern у main, getline іcopy зайві. В дійсності, загальною практикою є розміщення всіх означень зовнішніх змінних напочатку вихідного файла, уникаючи таким чином оголошень extern.

Якщо програма розміщена в декількох вихідних файлах, і якусь змінну, означену у файлі1, було використано у файлі2 і файлі3, тоді оголошення extern — обов'язкові у файлі2 та файлі3 для поєднання використань змінної. Звичною практикою є зібрати всі оголошення extern змінних і функцій в окремий файл, історично названий файлом заголовка, оскільки його включено директивою #include в заголовок кожного вихідного файла. Традиційним суфіксом назв файлів заголовка є .h. Функції стандартної бібліотеки, наприклад, оголошено у файлі заголовка на зразок <stdio.h>. Цю тему розглянуто в повному обсязі у Розділі 4, а саму бібліотеку — уРозділі 7 і Додатку Б.

Через те, що спеціалізовані версії getline та copy не мають аргументів, логіка підказує, що їхні прототипи напочатку файла повинні виглядати як getline() та copy(). Але заради сумісності зі старшими C-програмами, стандарт розглядає порожній список аргументів, як оголошення старого стилю, і вимикає будь-яку перевірку списку аргументів; треба використати слово voidдля відверто порожнього списку аргументів. Ми обговоримо це далі у Розділі 4.

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

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

Досі, ми охопили те, що можна назвати традиційним осердям мови програмування C. З цим набором складових можна писати корисні програми значного розміру, і було би непогано, якби ви призупинилися на деякий час, щоб зайнятися цим. Наступні вправи пропонують дещо складніші програми, ніж ті, які ми бачили в цьому розділі.

Вправа 1-20. Напишіть програму detab, яка би замінювала табуляцію у вводі на відповідну кількість пробілів. Припустіть сталий крок табуляції, скажімо кожний n-нний стовпчик. Чи має бути n змінною, чи символічною константою?

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

Вправа 1-23. Напишіть програму, яка би вилучала всі коментарі з вихідного файла C. Не забувайте про видалення залапкованих ланцюжків і символьних констант. Коментарі в C не гніздуються.

Вправа 1-24. Напишіть програму, яка би перевіряла C-програми на елементарні синтаксичні помилки, як от невідповідність круглих, фігурних і квадратних дужок. Не забувайте про одинарні та подвійні лапки, екрановані послідовності, коментарі. (Ця програма важка, якщо ви зробите її загальною.)


<== попередня лекція | наступна лекція ==>
Символьні масиви | Назви змінних


Онлайн система числення Калькулятор онлайн звичайний Науковий калькулятор онлайн