Время жизни и область видимости программных объектов

Объявления переменных

Объявление переменных допустимо без указания класса памяти или использовать спецификатор класса памяти static или extern.

Объявление статических переменных на глобальном уровне может задаваться в следующих формах:

· Переменная объявлена с классом памяти static. Такая переменная может быть инициализирована явно константным выражением или по умолчанию нулевым значением. Таким образом, объявления static int i=0 и static int iэквивалентны, и в обоих случаях переменной i будет присвоено значение нуль;

· Переменная объявлена без указания класса памяти, но с явной инициализацией. Такой переменной по умолчанию присваивается класс памяти static. Таким образом, объявления int i=1 и static int i=1 будут эквивалентны.

Объявление внутри блока переменной класса static позволяет создать переменную с глобальным временем жизни, но с локальной видимостью.

Рассмотрим пример.

Функция print выводит на экран значения статической переменной stat, автоматической переменной av, параметра функции p:

#include <stdio.h>

void print(int); //Прототип функции print()

int main(void)

{

int count;

for(count=9; count>=5; count-=2)

print(count); //Вызов функции print()

return 0;

}

//Определение функции print()

void print(int p)

{

int av=1;

static int stat=1;

printf("p=%d stat=%d av=%d\n",p,stat,av);

stat++;av++;

return 0;

}

Переменная p получает свое значение из функции main(), меняющееся от 9 до 5 с шагом 2. Статическая переменная stat создается в сегменте данных при первом вызове функции print() и получает начальное значение, равное единице. Функция увеличивает это значение на единицу. Переменная stat находится в сегменте данных, при повторном вызове функции print() переменная stat «вспоминает» свое прошлое значение. Локальная (автоматическая) переменная av при каждом вызове функции создается заново, каждый раз инициализируется и при выходе из функции перестает существовать.

В результате выполнения этого примера на экран будет выведена следующая информация:

p=9 stat=1 av=1

p=7 stat=2 av=1

p=5 stat=3 av=1

Глобальная переменная может быть определена только один раз в пределах своей области видимости. В другом исходном файле может быть объявлена другая глобальная переменная с таким же именем и с классом памяти static, конфликта при этом не возникает, так как каждая из этих переменных будет видимой только в своем исходном файле.

Внешняя переменная представляет собой ссылку на глобальную переменную с таким же именем. Внешние переменные могут объявляться как на внешнем уровне, так и внутри блока. Внешние переменные могут объявляться как в файлах, не содержащих глобальную переменную, так и в файлах, где эта переменная объявлена. Глобальная переменная видима в пределах файла, в котором она объявлена, начиная с места объявления. Выше своего описания и в других файлах эта переменная невидима. Создание внешней переменной класса extern в качестве ссылки на глобальную переменную, объявленную в другом месте программы, расширяет область видимости этой переменной. При этом область видимости глобальной переменной расширяется от места объявления внешней переменной до конца файла или блока, в котором сделано объявление.

В объявлениях с классом памяти extern не допускается инициализация, так как эти объявления ссылаются на уже существующие и определенные ранее переменные. Переменная, на которую делается ссылка с помощью спецификатора extern, может быть определена только один раз в одном из исходных файлов программы.

Рассмотрим следующий пример. Глобальная переменная a объявлена в середине текста программы таким образом, что функция summa() находится вне области видимости переменной. Чтобы функция summa() могла использовать переменную a, внутри функции объявляется внешняя переменная:

#include <stdio.h>

void summa()

{

extern float a;

float b=8;

float y=a+b;

printf("Summa=%f\n",y);

}

float a=10;

int main()

{

summa();

return 0;

}

После завершения работы программы на экран будет выведено значение 18.

Объявления функций

Функции всегда определяются на внешнем уровне, т. е. глобально. Объявления функций (прототипы) могут находиться как на глобальном, так и на локальном уровнях.

Функции могут быть объявлены с классом памяти static или extern.

Правила определения области видимости для функций отличаются от правил видимости для переменных и состоят в следующем:

· Функция, объявленная как static, видима в пределах того файла, в котором она определена. Каждая функция может вызвать другую функцию с классом памяти static из своего исходного файла, но не может вызвать функцию, функция, объявленная как static, видима в пределах того файла, в определенную с классом static в другом исходном файле. Разные функции с классом памяти static, имеющие одинаковые имена, могут быть определены в разных исходных файлах, и это не ведет к конфликту;

· Функция, объявленная с классом памяти extern, видима в пределах всех исходных файлов программы. Любая функция может вызывать функции с классом памяти extern;

· Если в объявлении функции отсутствует спецификатор класса памяти, то по умолчанию принимается класс extern.

Все объекты с классом памяти extern компилятор помещает в объектном файле в специальную таблицу внешних ссылок, которая используется редактором связей для разрешения внешних ссылок. Часть внешних ссылок порождается компилятором при обращениях к библиотечным функциям C, поэтому для разрешения этих ссылок редактору связей должны быть доступны соответствующие библиотеки функций.

Рассмотрим пример, состоящий из трех файлов исходного текста программы, образующих проект:

1.cpp

#include "fn.h"

int B()

{

return 10;

}

static int C()

{

return 15;

}

fn.h

int B();

int C();

fn.cpp

#include <stdio.h>

#include "fn.h"

int main()

{

int A=B()+C();

printf("%d\n",A);

return 0;

}

При компиляции проекта появится сообщение об ошибке: неизвестный символ C() в файле *.cpp. Причина такой ошибки в том, что функция C() – статическая и не может быть вызвана из другого модуля проекта.

Подробнее о способах разработки программ на основе проектов будет рассказано далее.

Время жизни и область видимости программных объектов

Время жизни объектов программы определяется по следующим правилам:

· Переменная, объявленная глобально, т. е. вне всех блоков, существует на протяжении всего времени выполнения программы;

· Локальные переменные, т. е. объявленные внутри блока, а также переменные с классом памяти register или auto, имеют время жизни только на период выполнения того блока, в котором они объявлены. Если переменная объявлена внутри блока с классом памяти static или extern, то она имеет время жизни на период выполнения всей программы;

Видимость переменных и функций в программе определяется следующими правилами:

· Переменная, объявленная или определенная глобально, видима от точки объявления или определения до конца исходного файла. Можно сделать переменную видимой и в других исходных файлах, для чего в этих файлах следует ее объявить с классом памяти extern;

· Переменная, объявленная или определенная локально, видима от точки объявления или определения до конца текущего блока;

· Переменные из объемлющих блоков, включая переменные, объявленные на глобальном уровне, видимы во внутренних блоках. Эту видимость называют вложенной. Если переменная, объявленная внутри блока, имеет то же имя, что и переменная, объявленная в объемлющем блоке, то это разные переменные, и переменная из объемлющего блока во внутреннем блоке будет невидимой;

· Функции с классом памяти static видимы только в том файле, в котором они определены. Остальные функции видимы во всей программе;

· Метки в функции видимы в пределах данной функции;

· Имена формальных параметров, объявленные в списке параметров прототипа функции, видимы только от точки объявления параметра до конца объявления функции.

Наши рекомендации