Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
Локальные и глобальные переменные.
Любые переменные, объявленные внутри функции, имеют сравнительно короткое время жизни, существуя в памяти компьютера только тогда, когда функция работает. Такие переменные называются локальными. Например, целая переменная i локальна для функции CountUp() в примере, рассмотренном выше. Переменная i в строке 15 и переменная i в строке 24 листинга 3.1 являются двумя разными переменными. Переменные, объявленные вне функций, – это глобальные переменные. Из записи программного фрагмента: int global; /* global – вне функции main() */ main() { int local; /* local – внутри main() или другой функции */ ... } следует, что любые программные операторы могут пользоваться переменной global, а к переменной local имеют доступ только операторы внутри функции main(). Важная особенность: в отличие от локальных, глобальные переменные всегда инициализируются нулевыми значениями. Таким образом, значение переменной global в приведенном фрагменте равно нулю, а значение local – не определено. Допустим, та же самая программа определяет функцию вида void AnyFn(void) { global = 5; /* все нормально */ local = 6; /*??? */ ... } При этом присваивание переменной local не будет скомпилировано. Эта локальная переменная определена в функции main() и нигде больше не существует. Умение правильно пользоваться локальными переменными определит ваш успех в программировании на С. Рассмотрим подробнее их некоторые важные характеристики. Классы памяти. Автоматические переменные. Внешние и статические переменные. Классы памяти: - динамическая память, которая выделяется при вызове функции и освобождается при выходе из нее (атрибуты: auto - автоматический; register - регистровый); - статическая память, которая распределяется на этапе трансляции и заполняется по умолчанию нулями (атрибуты: внешний – extern, статический – static). Автоматические переменные: Переменные, декларированные внутри функций, являются внутренними и называются локальными переменными. Никакая другая функция не имеет прямого доступа к ним. Такие объекты существуют временно на этапе активности функции. Каждая локальная переменная существует только в блоке кода, в котором она объявлена, и уничтожается при выходе из него. Эти переменные называют автоматическими и располагаются в стековой области памяти. По умолчанию, локальные объекты, объявленные в теле функции, имеют атрибут класса памяти auto. Принадлежность к этому классу можно также подчеркнуть явно с помощью ключевого слова auto. Например: void main(void) { auto int max, lin; ... } так поступают, если хотят показать, что определение переменной не нужно искать вне функции. Регистровая память (атрибут register) - объекты целого типа и символы рекомендуется разместить не в оперативной памяти, а в регистрах общего назначения (процессора), а при нехватке регистров - в стековой памяти (размер объекта не должен превышать разрядности регистра), для других типов компилятор может использовать другие способы размещения, а может просто проигнорировать данную рекомендацию. Регистровая память позволяет увеличить быстродействие программы, но к размещаемым в ней объектам в языке Си (но не С++) не применима операция адресации &, а также это неприменимо для массивов, структур, объединений и переменных с плавающей точкой. Внешние переменные: Объекты, размещаемые в статической памяти, декларируются с атрибутом static и могут иметь любой атрибут области действия. Глобальные объекты всегда являются статическими. Атрибут static, использованный при описании глобального объекта, предписывает ограничение его области применимости только в пределах остатка текущего файла. Значения локальных статических объектов сохраняются при повторном вызове функции. Таким образом, в языке С ключевое слово static имеет разный смысл для локальных и глобальных объектов. Переменная, описанная вне функции, является внешней переменной. Их еще называют глобальными переменными. Так как внешние переменные доступны всюду, их можно использовать вместо списка аргументов для передачи значений между функциями. Внешние переменные существуют постоянно. Они сохраняют свои значения и после того, как функции, присвоившие им эти значения, завершат свою работу. При отсутствии явной инициализации для внешних и статических переменных гарантируется их обнуление, автоматические и регистровые переменные имеют неопределенные начальные значения («мусор»). Внешняя переменная должна быть определена вне всех функций. При этом ей выделяется фактическое место в памяти. Такая переменная должна быть описана в каждой функции, которая собирается ее использовать. Это можно сделать либо явным описанием extern, либо по контексту. Чтобы функция могла использовать внешнюю переменную, ей нужно сообщить идентификатор этой переменной. Один из способов - включить в функцию описание extern. В определенных ситуациях описание extern может быть опущено: если внешнее определение переменной находится в том же файле, раньше ее использования в некоторой конкретной функции, то не обязательно включать описание extern для этой переменной в саму функцию. Фактически, обычная практика заключается в помещении определений всех переменных в начале исходного файла и последующем опусканием всех описаний extern. Включение ключевого слова extern позволяет функции использовать внешнюю переменную, даже если она определяется позже в этом или другом файле. Важно различать описание внешней переменной и ее определение. Описание указывает свойство переменной, ее размер, тип и т. д.; определение же вызывает еще и отведение памяти. Например, если вне какой-либо функции по- являются строчки: int sp; double val[20]; то они определяют внешние переменные sp и val, вызывают отведение памяти для них и служат в качестве описания для остальной части этого исходного файла. В то же время строчки: extern int sp; extern double val []; описывают в остальной части этого исходного файла переменную sp как int, а vol как массив типа double, но не создают переменных и не отводят им места в памяти. Во всех файлах, составляющих исходную программу, должно содержаться только одно определение внешней переменной. Другие файлы могут содержать описание extern для доступа к ней. Любая инициализация внешней переменной проводится только в декларации. В декларации должны указываться размеры массивов, а в описании extern этого можно не делать. Например, в файле 1: int sp = 0; double val [20]; ... в файле 2: extern int sp; extern double val []; ... В Си есть возможность с помощью #include иметь во всей программе только одну копию описаний extern и вставлять ее в каждый файл во время его компиляции. Если переменная с таким же идентификатором как внешняя декларирована в функции без указания extern, то тем самым она становится внутренней в данной функции. Не стоит злоупотреблять внешними переменными. Такой стиль программирования приводит к программам, связи данных внутри которых не вполне очевидны. Переменные при этом могут изменяться неожиданным образом. Программу становится трудно модифицировать. Файл 1: Файл 2: int x, y; char str[ ] = “Rezult = ”; void main(void) { ... } void fun1(void) { y = 15; cout < < str < < y; } extern int x, y; extern char str[ ]; int r, q; void fun2(void) { x = y / 5; cout < < str < < x; } void fun3(void) { int z= x + y; cout < < str < < z; } Декларация структур. Структура – тип данных, созданный пользователем, построенный с использованием других типов. Ключевое слово struct начинает определение структуры. struct имя_структуры { тип1 имя_переменной; тип2 имя_переменной; тип3 имя_переменной; и т.д. }; Например: struct Man { char fam[20]; char name[15]; int year, day, month; }; Среди типов данных структуры могут также присутствовать, кроме стандартных типов данных (int, float, char и т.д.) ранее определенные типы, но структура не может включать в себя переменные своего типа. При непосредственной работе со структурой, доступ к компонентам структуры осуществляется с помощью оператора «точка», а при использовании указателя на структуру «-> ». Синтаксис для доступа к компонентам структуры следующий: имя_переменной_структуры.член_данных имя_переменной_структуры.-> член_данных
|
Последнее изменение этой страницы: 2017-03-14; Просмотров: 536; Нарушение авторского права страницы