Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
DOROGOVA.pdf
Скачиваний:
245
Добавлен:
05.06.2015
Размер:
853.4 Кб
Скачать

Вопросы для самопроверки

1.Что такое указатель?

2.Что определяет тип указателя?

3.Для чего используется операция &?

4.Что означает операция "разадресации"? Какие синонимы этого понятия Вы знаете?

5.Приведите пример установки указателя на переменную.

6.Является ли обязательной инициализация указателя при его определении?

7.Приведите пример использования указателя в выражении.

8.Что означает термин "адресная арифметика"?

9.Какие особенности адресной арифметики Вы знаете?

10.Поясните особенности применения операции инкремента и декремента к указателю.

11.Поясните особенности применения операции сложения к указателю.

12.Поясните особенности применения операции вычитания к указателю.

13.Можно ли сравнивать указатели?

14.Можно ли присвоить имя массива указателю?

15.Изложите методику обращения к элементам массива через указатель?

16.Приведите пример вывода на экран элемента массива и его адреса.

17.Что такое ссылка?

18.Является ли обязательной инициализация ссылки при её определении?

19.Можно ли ссылку перенаправить с одной переменной на другую?

PDF created with FinePrint pdfFactory Pro trial version http://www.fineprint.com

7. Время жизни и область видимости переменной

7.1. Общие понятия

При определении переменной компилятор выделяет для неё память, причем тип данных определяет размер выделенной памяти.

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

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

Программируя на языке С, мы всегда имеем дело с программными блоками, например тело функции main(), тело цикла, одна из альтернатив оператора if – все это программные блоки.

Различают два вида блоков:

составной оператор;

определение функции.

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

блоки могут включать в себя составные операторы;

блоки не могут включать в себя определения функций.

Программный модуль это файл с исходным текстом программы.

Время жизни программного объекта (объектом может быть переменная, функция и тому подобное)

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

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

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

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

Объект может быть видимым в пределах:

блока;

модуля (файла);

во всех модулях (если программа располагается в нескольких файлах).

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

Внутри блока или функции объявляются локальные переменные, они видимы в том блоке, в котором объявлены, и во всех вложенных блоках, если таковые есть.

Пример:

 

 

int q;

// глобальная переменная

void main()

{// +++++++ функция main(), объемлющий блок

int i;

// локальная переменная функции main()

 

{// ****** ***** вложенный блок

int k,l;// локальные переменные вложенного блока

 

}//**********************************

 

k++

// ошибка, переменной k здесь не существует

}//+++++++++++++++++++++++++++++++

Переменная q существует на протяжении всего времени выполнения программы, она видима во всех модулях программы.

Переменная i существует на протяжении выполнения функции main(), она видима внутри функции main(), то есть в текущем модуле программы.

PDF created with FinePrint pdfFactory Pro trial version http://www.fineprint.com

Переменные k и l существуют на протяжении выполнения вложенного блока, они создаются при входе во вложенный блок и уничтожаются при выходе из него. Переменная i видна во вложенном блоке, переменные k и l не видны вне "своего" блока (их там просто не существует).

7.2. Классы памяти

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

Ключевые слова для обозначения классов памяти и их иерархия в языке С представлены в таблице 7.1.

Таблица 7.1

Динамический

Статический

класс памяти

класс памяти

Локальное

Глобальное

время жизни

время жизни

Автома-

Регистро-

Статический

Статический

тический

вый

(внутренний)

(внешний )

 

 

 

 

 

 

аuto

register

static

extern

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

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

Внутренние переменные определяются внутри функций.

7.2.1. Автоматический класс памяти

Ключевое слово auto указывает на то, что объект располагается в локальной, автоматически распределяемой памяти, используется в операторах объявления в теле функций или внутри блоков операторов.

Вне блоков и функций этот спецификатор не используется.

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

Область видимости автоматической переменной также локальна и представляет собой функцию (или блок) в которой переменная объявлена.

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

Если инициализация переменных в объявлении отсутствует, то их начальное значение не определено и

содержат непредсказуемое значение ("информационный мусор").

Спецификатор auto явно используется редко, он подразумевается по-умолчанию при любом объявлении в теле функции или в блоке операторов.

7.2.2. Класс памяти register

Register ещё один спецификатор автоматического класса памяти, применяется к локальным объектам, и представляет собой "пожелание" к транслятору, по возможности размещать объект в регистре, а не в оперативной памяти компьютера.

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

PDF created with FinePrint pdfFactory Pro trial version http://www.fineprint.com

7.2.3. Класс static (внутренний статический класс памяти)

Cпецификатор static относит переменную к внутреннему статическому классу памяти. Переменная,

объявленная как static, располагается по фиксированному адресу в памяти компьютера, причем объявление может находиться как в теле функции или блоке операторов, так и вне оных.

Область видимости у переменных класса static локальна, то есть переменные доступны только в тех блоках или функциях, в которых объявлялись.

Время жизни static-переменных глобально, то есть они существуют с момента определения до конца выполнения всех модулей программы.

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

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

Явная инициализация static-переменной выполняется один раз перед началом программы, если же переменная не инициализируется, то ей присваивается нулевое значение.

Сравнивая static-переменные с auto-переменными заметим, что явно инициализированная auto-

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

"информационный мусор".

7.2.4. Класс extern (внешний статический класс памяти)

Спецификатор extern делает переменную глобальной, то есть относит её к внешнему статическому классу памяти.

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

видимой и в других исходных файлах, для чего в этих файлах её также следует объявить со спецификатором extern.

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

7.3. Вложенные блоки в программе

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

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

Пример:

#include <stdio.h>

int gp=1; // внешнее объявление переменной void main()

{printf("\nmain\tgp=%d",gp);

{// блок1

int lp=0;//внутреннее объявление переменной

{gp++;lp++; // блок2 printf("\nblok2\tgp=%d\tlp=%d",gp,lp);

}

gp++;lp++;

printf("\nblok1\tgp=%d\tlp=%d",gp,lp);

}

gp++;lp++; // здесь lp не видна printf("\nmain\tgp=%d\tlp=%d",gp,lp); printf("\n");

}

Внешняя переменная gp видна в трёх блоках – main, блоке1 и блоке2, а локальная переменная lp видна в двуx блоках блоке1 и блоке2.

PDF created with FinePrint pdfFactory Pro trial version http://www.fineprint.com

// i=0,k=8
// i=1,k=8
объявляется три раза, фактически, объявляются три разные переменные
// i=2,k=7 //***********
// i=0 k=6

Поскольку переменная lp объявлена во вложенном блоке 1, то обращение к ней в теле функции main() приведет к ошибке, которая обнаружится на этапе трансляции.

Если переменная, объявленная внутри блока, имеет то же имя, что и переменная, объявленная в объемлющем блоке, то это две разные переменные, и переменная из объемлющего блока во внутреннем

блоке будет невидимой.

 

Пример:

 

 

 

 

int i=1;

// внешние (глобальные) объявления

int k=5;

 

 

void main(void);

 

{

 

 

k++;

 

 

рrintf( "%d %d\n", i, k );

// i=1,k=6

{// ++++++ объемлющий блок int i=0;

рrintf( "%d %d\n", i, k );

{ // ******* вложенный блок int i=2;

k++;

рrintf( "%d %d\n", i, k);

}

k++;

рrintf( "%d %d\n", i, k );

}//++++++++++

рrintf( "%d %d\n", i, k );

}

Обратите внимание, что имя i

содним и тем же именем:

в глобальной области;

в объемлющем блоке;

во вложенном блоке.

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

PDF created with FinePrint pdfFactory Pro trial version http://www.fineprint.com

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