- •Рецензенты:
- •Лекция 1 Основные понятия языка с
- •Первая программа
- •Переменные языка с
- •Имя переменной
- •Объявление константы
- •Операции языка с
- •Лекция 2 Операторы языка с Условный оператор
- •Оператор switch
- •Циклы Цикл for
- •Циклы while и do-while
- •Оператор безусловного перехода
- •Использование операторов break, continue и goto в циклах
- •Операция условие ?
- •Лекция 3 Массивы
- •Инициализация массивов
- •Массивы символов. Строки
- •Функции для работы со строками
- •Лекция 4 Указатели
- •Объявление указателей
- •Операции над указателями
- •Связь указателей и массивов
- •Массивы указателей
- •Инициализация указателей
- •Лекция 5 Функции языка с
- •Объявление функции
- •Оператор return
- •Прототипы функций
- •Функции c произвольным числом параметров
- •Область действия и область видимости переменной
- •Классы памяти
- •Параметры и аргументы функции
- •Лекция 6 Типы, определяемые пользователями
- •Структура
- •Перечислимый тип
- •Переименование типов-typedef
- •Лекция 7 Модели памяти и препроцессор языка с Модели памяти
- •Препроцессор языка с
- •Директива #define
- •Список рекомендуемой литературы
- •Оглавление
- •Программирование на языках высокого уровня: с
- •428015 Г.Чебоксары, Московский просп., 15
Область действия и область видимости переменной
Область действия (scope rules) переменной - это правила, которые устанавливают, какие данные доступны из данного места программы.
В языке С каждая функция - это отдельный блок программы. Попасть в тело функции нельзя иначе, как через вызов данной функции. В частности, нельзя оператора локального перехода goto перейти в середину другой функции.
С точки зрения области действия переменных различают три типа переменных: глобальные, локальные и формальные параметры. Правила области действия определяют, где каждая из них может применяться. Локальные переменные - это переменные, объявленные внутри блока, в частности внутри функции. Язык С поддерживает простое правило: переменная может быть объявлена внутри любого блока программы. Локальная переменная доступна внутри блока, в котором она объявлена. Вспомним, что блок и; открывается фигурной скобкой и закрывается фигурной скобкой. Область действия локальной переменной - блок.
Локальная переменная существует, пока выполняется блок, в котором эта переменная объявлена. При выходе из блока эта переменная (и ее значение) теряется.
Программа 5.14:
#include< stdio.h>
void f(void);
main(void) {
int i; i=1;
f();
рrintf('B функции main значение i равно %d\n", i); }
void f(void)
{ int i;
i =10;
printf(”B функции f() значение i равно %d\n", i); }
Пример показывает, что при вызове функции значение переменной i, объявленной в main(), не изменилось.
Формальные параметры - это переменные, объявленные при описании функций как ее аргументы. Функции могут иметь некоторое количество параметров, которые используются при вызове функций для передачи значений в тело функции. Формальные параметры могут использоваться в теле функции так же, как локальные переменные, которыми они по сути дела и являются. Область действия формальных параметров – блок, являющийся телом функции.
Глобальные переменные - это переменные, объявленные вне какой-либо функции. В отличие от локальных переменных глобальные переменные могут быть использованы в любом месте программы, но перед их первым использованием они должны быть объявлены. Область действия глобальной переменной - вся программа. Использование глобальных переменных имеет свои недостатки:
- они занимают память в течение всего времени работы программы;
- использование глобальных переменных делает функции менее общими и затрудняет их использование к других программах;
- использование внешних переменных делает возможным появление ошибок из-за побочных явлений.
Эти ошибки, как правило, трудно отыскать.
Классы памяти
В языке С есть инструмент, позволяющий управлять ключевыми механизмами использования памяти и создавать мощные и гибкие программы. Этот инструмент - классы памяти. Каждая переменная принадлежит к одному из четырех классов памяти. Эти 4 класса памяти описываются следующими ключевыми словами: auto - автоматическая, extern - внешняя, static - статическая, register - регистровая.
Тип памяти указывается модификатором - ключевым словом, стоящим перед спецификацией типа переменной. Например, Static int sum; register int plus;
Если ключевого слова перед спецификацией типа локальной переменной при ее объявлении нет, то по умолчанию она принадлежит классу auto, поэтому практически никогда это ключевое слово не используется. В этом просто нет необходимости.
Автоматические переменные (auto) имеют локальную область действия. Они известны только внутри блока, в котором они определены. Другие функции могут использовать то же имя, но это должны быть переменные, относящиеся к разным блокам. Автоматическая переменная создается (т. е. ей отводится место в памяти программы) при ходе в блок функции. При выходе из блока автоматическая переменная пропадает, а область памяти, в которой находилась эта переменная, считается свободной и может использоваться для других целей.
Автоматические переменные хранятся в оперативной памяти машины, точнее, в стеке. Регистровые (register) переменные хранятся в регистрах процессора. Доступ к временным, хранящимся в регистровой памяти, гораздо быстрее, чем к тем, которые хранятся в оперативной памяти компьютера. В остальном регистровые переменные аналогичны автоматическим переменным. Регистровая память процессора невелика, и если доступных регистров нет, то переменная становится простой автоматической переменной. Описание регистровой переменной имеет вид register int quick:
В большинстве случаев создатели компиляторов предусматривают оптимизацию программ, в частности используя регистровую память для размещения в ней переменных. Вторые активно используются в программе. Авторы компиляторов фирмы Borland утверждают, что оптимизация компиляторов по использованию регистровых переменных сделана так хорошо, что указание использовать переменную как регистровую может только ухудшить эффективность создаваемого машинного кода. В то же время в опциях интегрированной среды есть возможность задавать способы использования регистровых переменных:
• не использовать вообще;
• использовать только тогда, когда есть ключевое слово register;
•по усмотрению компилятора.
Внешняя переменная (extern) относится к глобальным переменным. Она может быть объявлена как вне, так и внутри тела функции
void f(void) { extern int j; /* объявление внешней переменной внутри функции */}
Появление ключевого слова extern связано с модульностью языка С, т.е. возможностью составлять многофайловую программу с возможностью раздельной компиляции каждого файла. Когда мы в одном из файлов опишем вне тела функции глобальную переменную float global, то для нее выделится место в памяти в разделе глобальных переменных и констант. Если мы используем эту глобальную переменную в другом файле, то при раздельной компиляции без дополнительного объявления переменной компилятор не будет знать, что это за переменная. Использование объявления extern float global не приводит к выделению памяти, а сообщает компилятору, что такая переменная будет описана в другом файле. И тогда при компоновке программы, состоящей из нескольких файлов, компоновщик будет искать описание этой переменной и связывать ее с использованием в других файлах. Объявление внешней переменной может быть как вне функции, так и внутри функции. Если это же имя переменной без ключевого слова extern будет объявлено внутри функции, то под этим именем будет создана уже другая автоматическая переменная. Можно к объявлению этой переменной добавить ключевое слово auto, чтобы показать, что не ошиблись, а намеренно продублировали имя. Объявлений переменной, как внешней, может быть несколько, в том числе и в одной функции в одном файле. Описание же переменной должно быть только одно. Следующие примеры демонстрируют разные способы описания внешних переменных:
int var;
/*описана внешняя переменная var */
main ()
{ extern int var, varl;/* объявлена та же внешняя переменная*/....
}
funcl() { extern int varl; /* объявлена внешняя переменная varl переменная var также внешняя. хотя она и не описана в этом блоке */..... }
func2() /* переменная var внешняя* /{
/* переменная varl невидима для этой функции в этом блоке */
}
int varl, /* описание внешней переменной */
funс3(){ /*для этой функции varl внешняя */
int var; /* переменная var описана как
локальная и не связана с глобальной переменной var. По
и умолчанию эта переменная автоматическая */}
func4(){ /*здесь переменная var является внешней глобальной переменной */
aulo int varl; /* переменная varl локальная автоматическая переменная */...}
При описании статических переменных перед описанием типа ставится ключевое слово static. Область действия локальной статической переменной - вся программа. Место в памяти под локальные статические переменные выделяется в начале работы программы в разделе глобальных и статических переменных. Однако область видимости локальных статических переменных такая же, как и у автоматических. Значение статических переменных сохраняется от одного вызова функции до другого. Локальные статические переменные инициализируются нулем, если не указан другой инициализатор. При этом описание с инициализацией Static int count = 10; локальной статической переменной count вызывает однократную инициализацию переменной count при выделении под нее места. При последующих вызовах функции, в которой описана эта переменная, инициализации не происходит. Это позволяет использовать такую переменную для счетчика количества вызовов функции.
Программа 5.15:
#include <stdio.h>
void trystat(void);
main(void)
{ int i;
for(i = l;I<=3; i++)
{ printf( "invocation # %d \n". i);
trystat():
priritf(“invocation # %d\n", i);
trystat (): }
return 0: }
void trystat(void)
{ int auto_ 1=1;
static int stat_l=l;
printf(“auto_1=%d stat_l =%d\n", auto_l++, stat_l++);}
Можно описать также глобальную(внешнюю) статическую переменную, то есть описать переменную типа static вне любой функции. Отличие внешней переменной от внешней статической переменной состоит в области их действия. Обычная внешняя переменная может использоваться функциями в любом файле, в то время как внешняя статическая переменная только функциями того файла, где она описана, причем только после ее определения. Все глобальные переменные - и статистические, и нестатические - инициализируются нулем, если не предусмотрено другой инициализации.
В таблице приведены область действия и продолжительность существования переменных разных классов памяти:
Таблица
Классы памяти |
Ключевое |
Время существования |
Область действия |
Автоматический |
auto |
временно |
блок |
Продолжение таблицы
Классы памяти |
Ключевое |
Время существования |
Область действия |
Регистровый |
register |
временно |
блок |
Статически локальный |
static |
постоянно |
блок |
Статически глобальный |
static |
постоянно |
файл |
Внешний |
extern |
постоянно |
программа |
В программе может быть описано несколько переменных с одним и тем же именем в разных блоках. В нижеприведенном модельном примере объявлена одна глобальная переменная и три локальных переменных с одним и тем же именем var.
Программа 5.16:
#include <stdio.h>
void f(void);
void fl(void);
{ int var=7
global variable
main ()
}
printf(“global variable in main var= %d \n", var); //var=7
tun()
printf("global variable in main after fun() var= %d \n", var);//var==8
int var 10; //local variable that overdose the global variable
printf("var = %d \n", var); /* var = 10 */
var++;
printf("in main var == %d \n ", var++); /* var =11*/
f()
printf(“in main var = %d \n ". var++); /* var = 12 */
fl();
printf("in main vair=%id\n", var ++); /* var = 13 '"/
fl()
printf(“in main var = %d \n ". var ++); /* var = 14 */
int var = 200; // local variable
printf (“int main var = %d \n ", var); /* var = 200 */
var ++; }
return 0;
}
void f(void)
{int var-77;/*local */
printf( "inf () var = %d \n ", var ); /* var = 77 */
var++;
}
void fl (void)
{
prinf("in fl() var = %d \n ", var); /* var = 8 or 9 */
var++; }
printf(“in fun ()var=%d\n ", var);/* var = 7 */
. var++; }
