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

Область действия и область видимости переменной

Область действия (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++; }

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