Переменные

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

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

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

● Определяющее объявление или просто определение. Это объявление переменной, одновременно являющееся определением.

● Ссылочное объявление. Это объявление, не являющееся определением.

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

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

В зависимости от контекста, в котором находится определение, различают две категории переменных:

● локальные,

● внешние.

Локальной переменной называется переменная, определение которой находится в теле функции. Определение внешней переменной записывается вне функций.

Объявление локальной переменной одновременно является и ее определением. Это упрощает работу с такими переменными.

При работе с внешними переменными возникают определенные сложности. Дело в том, что программный код, в котором создается такая переменная, может быть далеко расположен от ее использующего программного кода. В этом случае в программном коде, в котором эта переменная применяется, может потребоваться объявление переменной. В ссылочном объявлении переменной обычно используется зарезервированное слово extern.

В стандарте С89 появилась возможность использования в определении переменных зарезервированного слова const. В связи с этим переменные, с которыми работает программа на языке Си, можно разделить на две категории:

● изменяемые переменные – переменные, в определениях которых не используется зарезервированное словоconst,

● неизменяемые переменные – переменные, в определениях которых используется зарезервированное словоconst.

Переменная характеризуется следующими атрибутами:

● Имя.

● Тип.

● Адрес.

● Область действия.

● Время жизни.

● Связывание.

Остановимся кратко на новых понятиях, к которым относятся: область действия, время жизни и связывание.

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

● Блок (последовательность объявлений и инструкций, заключенная в фигурные скобки); блоком является тело функции, но тело может содержать вложенные в него блоки.

● Файл.

Время жизни определяет промежуток времени, в пределах которого за переменной сохраняется выделенная для нее память. Стандарт определяет две разновидности времени жизни:

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

● Статическое.

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

Статическое время жизни совпадает со временем выполнения программы. Такое время жизни имеют все внешние переменные. Локальная переменная будет иметь статическое время жизни в том случае, если в ее объявлении использовать зарезервированное слово static.

Связывание устанавливает взаимосвязь (если она существует) между различными “появлениями” одного и того же имени переменной. Стандарт языка Си определяет три вида связывания:

● Внешняя,

● Внутренняя

● Отсутствие связывания.

Внешнее и внутреннее связывание могут иметь только внешние переменные. Последний вид связывания (отсутствие связывания) имеют локальные переменные. Только переменные, имеющие внешнее связывание, доступны компоновщику. Это позволяет переменную (например, m), созданную в одном файле (например, f1.c), сделать доступной в другом файле (например, f2.c). Для этого в файле f2.c необходимо написать ссылочное объявление переменной m. Внутреннее связывание позволяет переменную “запрятать” в том файле, в котором она создана. Все внешние переменные по умолчанию имеют внешнее связывание. Для переменной можно установить внутреннее связывание, воспользовавшись в ее определении зарезервированным словом static.

Переменная может быть инициализирована во время своего объявления. Инициализация переменной состоит в назначении ей начального значения. Для этого объявление переменной должно содержать специальный элемент, который называют инициализатором. Объявление переменной, содержащее инициализатор, всегда является одновременно и ее определением. С переменными можно выполнять только две операции:

● Чтение,

● Запись.

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

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

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

спецификатор_типа список_переменных

В этом случае определение явно устанавливает только тип переменных с помощью элемента спецификатор_типа. Определение распространяется на все переменные, перечисленные в элементе список_переменных. Значения остальных атрибутов объявляемые переменные получают в соответствии с принципом умолчания.

Пример 1.

/* Файл f1.c */
int m;
static int n;
int main(void)
{
double x, y;
/* Переменные m и n доступны */
/* */
return 0;
}

/* Файл f2.c */
extern int m; /* Ссылочное объявление переменной m*/
/* Переменная m доступна */

В этом программном коде имеются пять объявлений. Четыре из них находятся в файле f1.c. Все эти объявления относятся к категории определяющих объявлений. С помощью этих объявлений устанавливаются типы, и выделяется память для четырех переменных: m, n, x и y. В начале определены две целочисленные переменные m и n. Обе переменные являются внешними. Их область действия начинается от точки определения и распространяется до конца файла f1.c. В связи с этим переменные m и n доступны в теле функции main(). Переменная m имеет внешнее связывание. Это означает, что ее можно сделать доступной в любом другом файле программы. Например, она будет доступна в файле f2.c. Доступной ее в файле f2.c делает наличие в нем ссылочного объявления этой переменной. Время жизни этих переменных совпадает со временем выполнения программы.

Переменная n имеет внутреннее связывание. Это обусловлено наличием в ее объявлении зарезервированного слова static. В файле f2.c эта переменная не доступна.

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

Рассмотрим теперь более детально вопрос об инициализации переменных во время их объявления. Следует отметить, что эта операция должна для каждой переменной выполняться индивидуально. Для инициализации некоторой переменной необходимо записать оператор присваивания “=”, затем записывается инициализатор. Следует отметить, что для внешних переменных в качестве инициализатора можно использовать только так называемые константные выражения, а при инициализации локальных переменных допустимо использовать выражения общего вида. Приведем пример.

Пример 2.

int m = 10;
int main(void)
{
double x = 1;
double y = sin(x);
/* ... */
return 0;
}

В этом примере инициализированы во время объявления три переменные: внешняя переменная m и две локальные переменные x и y.

Наконец приведем пример объявления константной переменной. Как указывалось ранее, в объявлении такой переменной следует использовать зарезервированное слово const.

Пример 3.

const intMaxSize = 100;
int main(void)
{
MaxSize = 200; /* Ошибка. Значение MaxSize изменять
нельзя */
/* */
}

В этом примере объявлена неизменяемая переменная MaxSize. Значение этой переменной зафиксировано в момент ее объявления и не может быть изменено в процессе выполнения программы.