Модуль — файл — функция — блок

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

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

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

Временем жизни является период выполнения программы или ее части, когда возможна работа с указанным объектом, т. е. время выполнения программы (модуля), функции или блока.

Внешний и внешний статический классы.

Описание переменных внешнего класса выполняется с помощью описателя extern

еxtern тип имя_объекта;

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

Областью видимости в этом случае является весь модуль, а временем жизни — время исполнения программы. Данные внешнего класса хранятся в сегменте данных.

Следующий пример представляет однофайловый проект, в котором переменные i и j определены во внешнем классе, поэтому видимы во всей программе, в том числе и в функциях main() и f1()

#include <stdio.h>

int i,j;

main()

{

f1();

printf("i= %d j=%d \n",i,j); }

f1()

{

i=10;

j=20;

return; }

Второй пример представляет двухфайловый проект, состоящий из файлов ext2a.c и ext2b.c

Файл ext2a.c #include <stdio.h> extern int i,j; main() { f1(3); printf("i= %d j=%d \n",i,j); } Файл ext2b.c int i,j; f1() { i=10; j=20; return; }

Переменные i и j во втором файле определены как объекты внешнего класса, поэтому в первом файле необходимо описание с указанием внешнего класса extern.

Внешний статический класс задается описателем static и уменьшает область видимости до размеров файла. Если модифицировать рассмотренный ранее пример следующим образом

Файл ext2a.c #include <stdio.h> extern int i,j; main() { f1(3); printf("i= %d j=%d \n",i,j); } Файл ext2b.c int i; static int j;//!!! f1() { i=10; j=20; return; }

то при связывании объектных модулей загрузчик выдаст сообщение об ошибке примерно такого вида

in function main()undefined refrence to j, unresolved externals: j in file(s) ext2a.c.

Замечание: по умолчанию все функции в С имеют внешний класс хранения и поэтому в описателе extern не нуждаются.

Локальный (автоматический) и локальный статический классы.

Описание переменных локального класса выполняется с помощью описателя auto

auto тип имя_объекта;

Определение для внешнего класса должно находиться внутри блоков и функций. Областью видимости в этом случае является блок или функция, а временем жизни — время исполнения блока или функции. Местом хранения данных локального класса является сегмент стека.

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

#include <stdio.h>

main()

{

int i=1,j=2;

printf("Вне блока i= %d j=%d \n",i,j);

{

auto int i=10;

printf("Внутри блока i= %d j=%d \n",i,j);

}

printf("Вне блока i= %d j=%d \n",i,j);

}

Выдача на терминал имеет вид:

Вне блока i= 1 j= 2

Внутри блока i= 10 j= 2

Вне блока i= 1 j= 2

Замечание. Описатель auto устанавливается для определяемых внутри блока или функции переменных по умолчанию, поэтому его можно опустить.

Внешний статический класс (задается описателем static) устанавливает время жизни переменной равным времени исполнения всей программы, не изменяя области видимости (в пределах блока), поэтому значения переменных такого класса сохраняются в промежутках между обращениями к блоку или функции.

Следующий пример демонстрирует сохранение значения локальной статической переменной I в промежутках между вызовами функции f1(). Поэтому трехкратный вызов f1() выводит различные значения i

#include <stdio.h>

int main()

{

f1(); f1(); f1();

return 0;

}

int f1()

{

static int i=1;

printf("Функция f1() вызвана %d раз\n", i);

i=i+1;

return 0;

}

Результат выполнения программы — вывод на терминал:

Функция f1() вызвана 1 раз

Функция f1() вызвана 2 раз

Функция f1() вызвана 3 раз

Динамические объекты — это объекты, созданные с помощью специальных функций (malloc, calloc и др.) или операций (new, new[]). Временем жизни таких переменных управляет программист. Область видимости определяется видимостью указателей. Такие переменные расположены как правило в «куче» (heap). В современных многозадачных операционных системах при завершении приложения все динамические переменные также уничтожаются в связи с уничтожением кучи, связанной с данным приложением. Область видимости определяется областью видимости указателя, связанного с динамическим объектом.

Ещё один пример (С++).

int main()

{

char a = 5;

{

int b = a + 5; //здесь a существует и доступно

} //уничтожена переменная b

short c;

c = a + b; // ошибка, т.к. b уже не существует

for(int i = 0;i<10;i++) {…}

c = i; //ошибка, i существует только в теле цикла for

int i=0; //переменная может быть объявлена, т.к. i //объявленная выше уже не существует

for(;i<10;i++) {…}

c = i; //допустимо, т.к. i объявлено в этом же блоке

i = 10;

{

int i = 3; //допустимо, перекрывает видимость i, //объявленной ранее

}

// здесь i=10;

} //уничтожены переменные a,c,i


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



double arrow