Многофайловые Си-программы

Содержание

Слайд 2

Структура Си-программы описания функций, одна из которых обязательно main; прототипы (шаблоны)

Структура Си-программы

описания функций, одна из которых обязательно main;
прототипы (шаблоны) функций;
директивы препроцессора;
описания

глобальных переменных, констант, типов (т. е. описания глобальных имен, отличных от функций).

Программа на Си состоит из одного или нескольких файлов (текстовых). Содержание файлов программы:

Слайд 3

Структура Си-программы Язык "C" разрабатывался со стремлением сделать функции эффективными и

Структура Си-программы

Язык "C" разрабатывался со стремлением сделать функции эффективными и удобными

для использования; "C"-программы обычно состоят из большого числа маленьких функций, а не из нескольких больших. Программа может размещаться в одном или нескольких исходных файлах любым удобным образом; исходные файлы могут компилироваться отдельно и загружаться вместе наряду со скомпилированными ранее функциями из библиотек. Мы здесь не будем вдаваться в детали этого процесса, поскольку они зависят от используемой системы.
K&R
Слайд 4

Область действия имен Имена Локальное (внутреннее) Глобальные (внешние) описанное внутри функции

Область действия имен

Имена

Локальное (внутреннее)

Глобальные (внешние)

описанное внутри функции

доступно только в этой

функции

имя функций или другое имя, описанное вне функций

доступно в части программы от точки описания до конца файла

Область действия имени – часть программы, в которой это имя может быть использовано

Слайд 5

Глобальные (внешние) имена Имена функций. Эти имена видимы из всех файлов

Глобальные (внешние) имена

Имена функций. Эти имена видимы из всех файлов программы.

Однако шаблон функции действует только в пределе одного файла. Поэтому приходится помещать в каждый файл программы прототипы используемых в этом файле функций. Удобно это делать с помощью директивы include препроцессора.
Имена переменных, констант, типов, объявленные вне функций. Если требуется воспользоваться таким глобальным именем вне области его действия (в области от начала файла до объявления имени или в другом файле), то нужно повторить объявление имени, предварив его описателем extern. Объявление extern не предусматривает распределение памяти; оно лишь делает нужное имя доступным.
Обратите внимание:
В инструкции extern невозможна инициализация.
Компилятор Си по описаниям глобальных переменных не только дает им место в памяти, но и обнуляет их. Локальные переменные при описании не обнуляются; их значения считаются неопределенными (если, конечно, они не заданы инициализацией, вводом или присваиванием).
Инструкции extern удобно вставлять с помощью include.
Слайд 6

Пример: область действия имен float a; int i; main () {

Пример: область действия имен

float a;
int i;
main ()
{ int

i;
extern float b;
a=...; b=...;
}
float f1()
{int i; a=...
}
float b;
a=...;
float f2()
{int i;a=...; b=...;
}

extern float a;
f3()
{a=...;
}
extern int c;
f4()
{ a=...
}
f5()
{
}
int c; . . .

файл 1

файл 2

Слайд 7

Пояснения к примеру Глобальная переменная а может использоваться во всех функциях

Пояснения к примеру

Глобальная переменная а может использоваться во всех функциях файла

1, т. к. она описана в самом начале файла 1; она также доступна всем функциям файла 2, потому что объявление extern float a стоит в начале файла 2.
Глобальная переменная i файла 1 недоступна ни одной функции этого файла, так как каждая функция имеет локальную переменную i. Описание int i приводит к выделению ячейки памяти под переменную i каждый раз при входе в блок {...},где стоит это описание; при выходе из блока эта ячейка освобождается. Локальные i доступны только в блоке своей функции, а глобальная i - во всем файле 1, за исключением этих функций.
Глобальная переменная b файла 1 может использоваться в функции f2, т. к. объявлена до описания f2. В функциях, описанных выше объявления b, эта переменная недоступна. Объявление extern float b в блоке функции main, позволяет этой функции использовать b; тем не менее, для f1 переменная b остается недоступной.
В файле 2 вместо двух объявлений int c и extern int c можно было бы оставить только int c, поместив его на место extern int c.
Слайд 8

Рекомендации по использованию локальных и глобальных переменных По возможности описания глобальных

Рекомендации по использованию локальных и глобальных переменных

По возможности описания глобальных переменных,

в том числе и extern, следует ставить в начало файла.
Не стоит делать глобальными промежуточные переменные (например, i в программе, приведенной ниже), потому что:
это делает подпрограмму менее универсальной, так как приводит к появлению непонятного пользователю "стыка" - промежуточной глобальной переменной;
приводит к неэкономному расходованию памяти, так как глобальные переменные занимают память в течение всего времени работы программы.
Слайд 9

Время жизни (существования) имени переменной или константы Данное Статическое Автоматическое Время

Время жизни (существования) имени переменной или константы

Данное

Статическое

Автоматическое

Время жизни – время, в

течение которого под данное распределена память.

Существует все время выполнения программы

Существует во время выполнения функции, в которой описаны

Динамическое

Получает место в памяти с помощью операторов динамического распределения памяти

Слайд 10

Статические данные Глобальные данные Статические локальные данные Доступны только функции, в

Статические данные

Глобальные данные

Статические локальные данные

Доступны только функции, в которой описаны, но

существуют (занимают память) во время выполнения всей программы

Данные, объявленные внутри функций как static

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

Статические данные распределены в специальном статическом сегменте памяти программы

Слайд 11

Автоматические данные Это, прежде всего, локальные данные функции, не объявленные как

Автоматические данные

Это, прежде всего, локальные данные функции, не объявленные как static.


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

Применение статических локальных данных Статические локальные переменные часто используются программами управления

Применение статических локальных данных

Статические локальные переменные часто используются программами управления ресурсами

- например, для подсчета числа обращений к программе.
Пример использования локальной статической переменной:
f(); /*шаблон*/
main()
{...f();f();...;f();/*переменная i будет накапливать число обращений*/
} /* к f*/
f()
{static int i=0;
/*инициализация работает один раз при первом входе в блок */
... i=i+1;
}
Слайд 13

Возможное расположение данных в памяти Статический сегмент программы Стек функций Динамическая память Регистры процессора

Возможное расположение данных в памяти

Статический сегмент программы
Стек функций
Динамическая память
Регистры процессора

Слайд 14

Класс памяти Класс памяти характеризует область действия, время жизни и расположение

Класс памяти

Класс памяти характеризует область действия, время жизни и расположение в

памяти переменных.
Существуют следующие описатели класса памяти:
auto - для переменных, действующих в пределах блока; обычно принимается по умолчанию.
register - тоже, что и auto, но для регистров процессора.
static - для описания статических переменных (имеет смысл для локальных переменных).
extern - делает доступными глобальные переменные, расширяя их область действия.