- •21. Основы и создание функций.
- •22. Функции, возвращающие нецелые значения.
- •23.Внешние переменные.
- •24. Область действия.
- •25. Заголовочные файлы.
- •26. Статические переменные.
- •27. Регистровые переменные.
- •28. Блочная структура.
- •29. Инициализация
- •30. Рекурсия.
- •31. Включение файла.
- •32. Макроподстановки.
- •33. Условное включение.
28. Блочная структура.
Внутри одной функции переменные можно определять в блочно-структурном стиле. Объявления переменных (в том числе инициализации) могут стоять после левой фигурной скобки, открывающей любой составной оператор, а не только после такой, которая открывает тело функции. Переменные, объявленные таким образом, блокируют действие любых переменных с теми же именами, объявленных во внешних блоках, и остаются в силе, пока не встретится соответствующая (закрывающая) правая скобка.
Рассмотрим пример:
if (n > 0) {
int i /* объявляется новая переменная i */
for (i = 0; i < n; i++)
}
В этом фрагменте кода область действия переменной i — та ветвь оператора if, которая соответствует "истине" в условии. Эта переменная не связана с любыми другими i за пределами блока. Автоматическая переменная объявляется и инициализируется в блоке всякий раз заново при входе в этот блок. Статическая переменная инициализируется только в первый раз при входе в блок.
Автоматические переменные, в том числе формальные параметры, также преобладают над внешними переменными и функциями с теми же именами, скрывая и блокируя действие их имен. Рассмотрим такое объявление:
int x;
int у;
f(double x)
{
double у;
}
Внутри функции f любое употребление имени х будет относиться к параметру функции, имеющему тип double; за ее пределами х будет обозначать внешнюю переменную типа int. To же самое справедливо в отношении переменной у.
29. Инициализация
При отсутствии явной инициализации для внешних и статических переменных гарантируется их обнуление; автоматические и регистровые переменные имеют неопределенные начальные значения ("мусор").
Скалярные переменные можно инициализировать в их определениях, помещая после имени знак = и соответствующее выражение:
int х = 1;
char squote = '\'';
long day = 1000L * 60L * 60L * 24L; /* день в миллисекундах */
Для внешних и статических переменных инициализирующие выражения должны быть константными, при этом инициализация осуществляется только один раз до начала выполнения программы. Инициализация автоматических и регистровых переменных выполняется каждый раз при входе в функцию или блок. Для таких переменных инициализирующее выражение - не обязательно константное. Это может быть любое выражение, использующее ранее определенные значения, включая даже и вызовы функции. Например, в программе бинарного поиска инициализацию можно записать так:
int binsearch(int х, int v[], int n)
{
int low = 0;
int high = n-1;
int mid;
}
а не так:
int low, high, mid;
low = 0;
high = n - 1;
В сущности, инициализация автоматической переменной - это более короткая запись инструкции присваивания. Какая запись предпочтительнее - в большой степени дело вкуса. До сих пор мы пользовались главным образом явными присваиваниями, поскольку инициализация в объявлениях менее заметна и дальше отстоит от места использования переменной.
Массив можно инициализировать в его определении с помощью заключенного в фигурные скобки списка инициализаторов, разделенных запятыми. Например, чтобы инициализировать массив days, элементы которого суть количества дней в каждом месяце, можно написать:
int days[] = {31, 28, 31, 30, 31, 30, 31. 31, 30, 31, 30, 31};
Если размер массива не указан, то длину массива компилятор вычисляет по числу заданных инициализаторов; в нашем случае их количество равно 12.
Если количество инициализаторов меньше числа, указанного в определении длины массива, то для внешних, статических и автоматических переменных оставшиеся элементы будут нулевыми. Задание слишком большого числа инициализаторов считается ошибкой. Инициализация символьных массивов - особый случай: вместо конструкции с фигурными скобками и запятыми можно использовать строку символов. Например, возможна такая запись:
char pattern[] = "ould";
представляющая собой более короткий эквивалент записи
char pattern[] = {'о', 'u', 'l', 'd', '\0'};
В данном случае размер массива равен пяти (четыре обычных символа и завершающий символ '\0').
