Модификатор тип_переменной имя_переменной

Все переменные в программе характеризуются не только типом, но и классом памяти. В языке Си существует четыре класса памяти: автоматический (automatic), регистровый(register), статический(static) и внешний(external).

 


6.3.1. Автоматические переменные.

Автоматическиепеременные в программе можно описать так:

auto A; auto char c1; auto int x= 125;

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

 

Пример:

 

#include <iostream.h>

main()

{

int t;

{

auto int t=2;

{

auto int t=3;

cout<<" t3 "<<t; // печатается значение 3

}

cout<<" t2 "<<t; // печатается значение 2

}

cout<<" t1 "<<t; // печатается 0

 

}

Результат:

t3 3

t2 2

t1 0

 

В этой программе переменная t описана в нескольких блоках, в каждом блоке она может принимать разные значения не зависимо от других. С ней могут выполнятся разные операции. В нашей программе значение переменной tвыводится на экран. В нашем случае выведутся числа 3, 2, и неопределенное число, так называемое число "мусор", так как переменной t не было присвоено значение во внешнем блоке.

(в некоторых случаях может быть и 0)


6.3.2. Внешние переменные.

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

 

Пример:

 

#include <stdio.h>

int x=145;//Описание внешней переменной
main()
{
extern int x,y;
printf("x=%d y=%d ",x,y);
}
int y=541; //Описание внешней переменной

Результатом работы программы будет вывод:

x=145 y=541

 

Внешние переменные могут определятся вне какой-либо функции; при этом выделяется фактическая память. В любой другой функции, обращающейся к этим переменным, они должны описываться; делается это явно с помощью описателя extern.

Обычно поступают так, как показано в приведенном выше примере .

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

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

int var;

main()

{extern int var;

}

func1()

{ extern int var;

}


Лекция 7.

 

Пример:

 

#include<iostream.h>

int x=3; /*описание внешней переменной */

/* увелечение x */

int plus1()

{

x=x+1;

cout<<" прибавляем единицу: x="<<x;

}

// обе функции “видят” одну и ту же переменную

/*уменьшение x */

int minus1()

{

x=x-1;

cout<<" вычитаем единицу: x="<<x;

}

main()

{

cout<<" начальное значение x="<<x;

plus1();

minus1();

minus1();

}

 

Результатом работы программы будет вывод:

 

начальное значение x=3

прибавляем единицу: x=4

вычитаем единицу: x=3

вычитаем единицу: x=2

 

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

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

static char c; static int a=1;

Рассмотрим пример, в котором переменная объявлена как статическая.

 


Пример

/*статические переменные*/

#include <iostream.h>

int x=10;

void plus1()

{

static int x=0;

x=x+1;

cout<<" x="<<x;

}

void minus1()

{

 

x=x-1;

cout<<" вычитаем единицу: x="<<x;

}

main()

{

plus1();

plus1();

plus1();

minus1();

}

Начальное значение равное нулю переменная x принимает только один раз. Затем в программе main, функция plus1()несколько раз запускается, при каждом запуске функции аргумент x не изменяется, а остается значение из предыдущей функции. Таким образом повторение функцииplus1обеспечивает увеличение переменной x на 1 при каждом запуске 1, 2, 3 ... При вызове функции minus используется начальное присваивание 10 и результат будет равен 9.

 

Результатом работы программы будет вывод:

 

x=1

x=2

x=3

вычитаем единицу: x=9

 


7.1.1. Регистровые переменные.

 

Регистровыепеременные объявляются в программе с помощью ключевого слова register и должны хранится в сверх быстрой памяти ЭВМ - регистрах. Используются аналогично автоматическим переменным. Целесообразность их применения - для увеличения быстродействия программы.

 

#include <iostream.h>

 

void plus1()

{

static int x=0;

x=x+1;

cout<<" x="<<x;

}

void minus1()

{

register int x=10;

x=x-1;

cout<<" вычитаем единицу: x="<<x;

}

main()

{

plus1();

plus1();

plus1();

 

minus1();

}

Результат выполнения программы не изменится.

 

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


Пример:

 

int x; // глобальное x

f() {

int x; // локальное x прячет глобальное x

x = 1; // присвоить локальному x

{

int x; // прячет первое локальное x

x = 2; // присвоить второму локальному x

}

x = 3; // присвоить первому локальному x

}

int* p = &x; // взять адрес глобального x


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

 

Пример:

 

#include <iostream.h>

int x;

f()

{

int x = 1; // скрывает глобальное x

::x = 2; // присваивает глобальному x

cout<<" x1= "<<x;

}

main()

{

 

f();

cout<<" x2= "<<x;

}

На экран будет выведено:

x1=1

x2=2
Возможности использовать скрытое локальное имя нет.

 


Область видимости имени начинается в точке описания. Это означает, что имя можно использовать даже для задания его собственного значения.

 

Пример:

 

int x;

f()

{

int x = x;

}


Это не является недопустимым, хотя и бессмысленно, и компилятор предупредит, что x "used before set" ("использовано до того, как задано"), если вы попробуете так сделать. Можно, напротив, не применяя операцию ::, использовать одно имя для ссылки на два различных объекта в блоке.

 

Пример:

 

#include <iostream.h>

int x;

f()

{

int x = 1; // скрывает глобальное x

::x = 2; // присваивает глобальному x

cout<<" x1= "<<x;

}

f1() {

int y = x; // глобальное x

int x = 22;

y =y+ x; // локальное x

cout<<"y="<<y;

}

main()

{

f();

f1();

cout<<" x2= "<<x;

}

 

На экран будет выведено:

x1= 1y=24

x2= 2

 


Переменная y инициализируется значением глобального x, 2, а затем к нему прибавляется значение локальной переменной x, 22.

 

Имена параметров функции считаются описанными в самом внешнем блоке функции, поэтому

f(int x)

{

int x; // ошибка

}

фрагмент программы содержит ошибку, так как x определено дважды в одной и той же области видимости.