Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
YAZbIki.doc
Скачиваний:
8
Добавлен:
16.03.2015
Размер:
758.78 Кб
Скачать

1.6.4. Инициализация глобальных и локальных переменных

При инициализации необходимо придерживаться следующих правил:

1. Объявления содержащие спецификатор класса памяти extern не могут содержать инициаторов.

2. Глобальные переменные всегда инициализируются, и если это не сделано явно, то они инициализируются нулевым значением.

3. Переменная с классом памяти static может быть инициализирована константным выражением. Инициализация для них выполняется один раз перед началом программы. Если явная инициализация отсутствует, то переменная инициализируется нулевым значением.

4. Инициализация переменных с классом памяти auto или register выполняется всякий раз при входе в блок, в котором они объявлены. Если инициализация переменных в объявлении отсутствует, то их начальное значение не определено.

5. Начальными значениями для глобальных переменных и для переменных с классом памяти static должны быть константные выражения. Адреса таких переменных являются константами и эти константы можно использовать для инициализации объявленных глобально указателей. Адреса переменных с классом памяти auto или register не являются константами и их нельзя использовать в инициаторах.

В приведенном примере глобальная переменная global_var имеет глобальное время жизни и постоянный адрес в памяти, и этот адрес можно использовать для инициализации

статического указателя global_ptr. Локальная переменная local_var, имеющая класс памяти auto размещается в памяти только на время работы функции func, адрес этой переменной не является константой и не может быть использован для инициализации статической переменной local_ptr. Для инициализации локальной регистровой переменной reg_ptr можно использовать неконстантные выражения, и, в частности, адрес переменной local_ptr.

Переменные

Переменная — это именованный участок памяти, в котором хранится значение, которое может быть изменено программой. Все переменные перед их использованием должны быть объявлены. Общая форма объявления[1]имеет такой вид:

тип список_переменных;

Здесь типозначает один из базовых или объявленных программистом типов (если необходимо — с одним или несколькими спецификаторами), асписок_переменныхсостоит из одного или более идентификаторов, разделенных запятыми. Ниже приведены примеры объявлений:

int i,j,l;

short int si;

unsigned int ui;

double balance, profit, loss;

Необходимо помнить, что в С имя переменной никогда не определяет ее тип.

Где объявляются переменные

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

Локальные переменные

Переменные, объявленные внутри функций, называются локальными переменными. В некоторых книгах по С они называютсядинамическими переменными[2]. В этой книге используется более распространенный терминлокальная переменная. Локальную переменную можно использовать только внутри блока, в котором она объявлена. Иными словами, локальная переменная невидима за пределами своего блока. (Блок программы — это описания и инструкции, объединенные в одну конструкцию путем заключения их в фигурные скобки.)

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

Чаще всего блоком программы, в котором объявлены локальные переменные, является функция. Рассмотрим, например, следующие две функции:

Целая переменная х объявлена дважды: один раз в func1() и второй — в func2(). При этом переменная х в одной функции никак не связана и никак не влияет на переменную с тем же именем в другой функции. Это происходит потому, что локальная переменная видима только внутри блока, в котором она объявлена, за пределами этого блока она невидима.

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

Из соображений удобства и в силу устоявшейся традиции все локальные переменные функции чаще всего объявляются в самом начале функции, сразу после открывающейся фигурной скобки. Однако можно объявить локальную переменную и внутри блока программы (блок функции — это частный случай блока программы). Например:

В этом примере локальная переменная s создается при входе в блок if и разрушается при выходе из него. Следовательно, переменная s видима только внутри блока if и не может быть использована ни в каких других местах, даже если они находятся внутри функции, содержащей этот блок.

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

Если имена переменных, объявленных во внутреннем и внешнем (по отношению к нему) блоках совпадают, то переменная внутреннего блока "прячет" (т.е. скрывает, делает невидимой) переменную внешнего блока. Рассмотрим следующий пример:

В этом примере переменная х, объявленная внутри блока if, делает невидимой внешнюю переменную х. Следовательно, внутренняя и внешняя х — это два разных объекта. Когда блок заканчивается, внешняя х опять становится видимой.

В стандарте С89 все локальные переменные должны быть объявлены в начале блока, до любого выполнимого оператора. Например, следующая функция вызовет ошибку компиляции в С89:

Однако в С99 (и в C++) эта функция вполне работоспособна, потому что в них локальная переменная может быть объявлена в любом месте внутри блока до ее первого использования.

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

По умолчанию локальные переменные хранятся в стеке. Стек — динамически изменяющаяся область памяти. Вот почему в общем случае локальные переменные не сохраняют свое значение в период между вызовами функций.

Локальные переменные можно инициализировать каким-либо заранее заданным значением. Это значение будет присвоено переменной каждый раз при входе в тот блок программы, в котором она объявлена.

Формальные параметры функции

Если функция имеет аргументы, значит должны быть объявлены переменные, которые примут их значения. Эти переменные называются формальными параметрамифункции. Внутри функции они фигурируют как обычные локальные переменные. Как показано в следующем фрагменте программы, они объявляются после имени функции внутри круглых скобок:

/* Возвращает 1, если в строке s содержится символ c, в противном

случае возвращает 0 */

int is_in(char *s, char c)

{

while(*s)

if(*s==c) return 1;

else s++;

return 0;

}

Функция is_in() имеет два параметра: s и с, она возвращает 1, если символ, записанный в переменной с, входит в строку s, в противном случае она возвращает 0.

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

Глобальные переменные

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

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

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

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

Статические и динамические переменные

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

Динамическая адресация нужна только тогда, когда количество поступающих на хранение данных заранее точно не известно. Такие данные размещают в специальных динамических структурах, тип которой выбирается в соответствии со спецификой задачи и с возможностями выбранной системы программирования. Это может быть стек,куча,очередьи т. п. Даже файл, в том смысле, который заложилН.ВиртвПаскаль, является динамической структурой.

Локальные и глобальные переменные. Области видимости

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

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]