Внешние переменные имеют статическую продолжительность хранения. Таким образом, массив Up существует и сохраняет свои значения независимо от того, выполняется main(), next() или какая-то другая функция.
В следующих трех примерах показаны четыре возможных комбинации внешних и автоматических переменных. В примере 1 присутствует одна внешняя переменная Hocus, которая известна и main(),и magic().

494 глава 12

В примере 3 создаются четыре переменных. Переменная Hocus в main() является автоматической по умолчанию и локальной для main(). Переменная Hocus в magic() явно объявлена как автоматическая и известна только magic(). Внешняя переменная Hocus не известна main() или magic(), но будет известна любой другой функции в данном файле, не имеющей собственной локальной переменной Hocus. Наконец, Pocus — это внешняя переменная, которая известна magic(), но не main(), потому что Pocus находится за main().

Приведенные примеры иллюстрируют область видимости внешних переменных, которая простирается от места их объявления и до конца файла. Они также отражают время жизни переменных. Внешние переменные Hocus и Pocus существуют на протяжении всего времени выполнения программы, а поскольку они не ограничены какой- то одной функцией, они не исчезают после завершения конкретной функции.
Инициализация внешних переменных
Как и автоматические, внешние переменные могут инициализироваться явно. В отличие от автоматических, внешние переменные по умолчанию инициализируются нулем, если вы не инициализировали их. Это правило применимо также к элементам внешне определенного массива. Однако для инициализации переменных с областью видимости в пределах файла можно использовать только константные выражения, что отличается от случая автоматических переменных.
int х = 10; // допустимо, 10 - это константа
int у=3+20; // допустимо, константное выражение
size_t z = sizeof(int); // допустимо, константное выражение int х2 = 2 * х; // недопустимо, х - это переменная
(При условии, что типом не является массив, выражение sizeof считается константным.)
Использование внешней переменной
Давайте рассмотрим простой пример, в котором задействована внешняя переменная. В частности, предположим, что две функции с именами main() и critic() должны иметь доступ к переменной units. Это можно сделать, объявив unit s за пределами ранее упомянутых двух функций, как показано в листинге 12.4. (Примечание: назначение данного примера — демонстрация работы внешней переменной, а не ее типичное применение.)
Классы хранения, связывание и управление памятью 495
Листинг 12.4. Программа global .с

Вот результаты пробного запуска:
Сколько фунтов весит маленький бочонок масла?
14
Вам не повезло. Попробуйте еще раз.
56
Вы знали это!
Обратите внимание, что второе значение для units читается функцией critic(), но main() также известно новое значение после завершения цикла while. Таким образом, и main(), и critic() используют идентификатор units для доступа к одной и той же переменной. В рамках терминологии С мы говорим, что переменная units имеет область видимости в пределах файла, внешнее связывание и статическую продолжительность хранения.
Мы сделали units внешней переменной, определив ее за пределами определений всех функций. Это и все, что необходимо сделать для обеспечения доступности units всем последующим функциям в файле.
Давайте посмотрим на некоторые детали. Прежде всего, объявление переменной units там, где оно находится, делает ее доступной объявленным далее функциям без дополнительных усилий. Следовательно, функция critics() пользуется переменной
units.
Аналогично, ничего не придется предпринимать для предоставления доступа к units функции main(). Однако в main() имеется такое объявление:
extern int units;
В рассматриваемом примере это объявление является главным образом формой документирования. Спецификатор класса хранения extern сообщает компилятору, что любое упоминание units в данной функции относится к переменной, объявленной за пределами этой функции, возможно, даже вне самого файла. И снова main() и critic() работают с внешне определенной переменной units.
Читать дальше