Классы памяти 1.1
int i=0; | i.0=0 (Обозначение x.n используется для того, чтобы показать обращение к переменной x, определенной в блоке уровня n1). Класс памяти переменной i.0 - внешний2. Область действия переменной i.0 есть любая программа, загружающаяся с данным файлом. Время существования i.0 - все время выполнения этой программы. |
1В любом месте текста программы уровнем блока называется число левых фигурных скобок ({) минус число правых фигурных скобок (}). Другими словами, это число текстуально открытых блоков. Самый внешний уровень в программе, т.е. когда еще нет ни одного блока, - это блок уровня 0.
2Вы можете спросить, почему класс памяти i не описывается явно с помощью служебного слова extern. Если только явно не описывается что-то другое, то класс памяти переменных, определяемых в блоке уровня 0, всегда считается extern. Связывание переменной со служебным словом extern не есть определение переменной. Это просто указание для транслятора, что эта переменная где-то в другом месте определена в блоке уровня 0.
main | |
{ | Теперь мы находимся в блоке уровня 1. |
auto int i=1; | i.1=1 (i относится к уровню 1). Класс памяти переменной i.1 - auto. Область действия i.1 - функция main. Время существования i.1 - все время выполнения main. |
PRINT1(d,i.1); | Если две переменные имеют одно и то же имя, то по этому имени обращаются к внутренней переменной, внешняя непосредственно недоступна. |
{ | Теперь мы находимся в блоке уровня 2. |
int i=2; | i.2=2 Класс памяти переменной i.2 - auto; таким по умолчанию будет класс памяти для переменных блоков уровня 1 и более. Область действия i.2 - блок управления 2, время существования - время существования этого блока. |
PRINT1(d,i.2); | |
{ | Теперь мы находимся в блоке уровня 3. |
i.2+=1; | i.2=3 |
PRINT1(d,i.2); | Печатается i.2, т.е. самая внутренняя переменная с именем i. |
} | Возвращаемся в блок уровня 2. |
PRINT1(d,i.2); | Опять печатается i.2. |
} | Переходим на уровень 1. Переменная i.2 исчезает. |
PRINT1(d,i.1); | С ее исчезновением самой внутренней переменной с именем i будет i.1. |
} | Возвращаемся на уровень 0. |
Классы памяти 2.1
int i=LOW; | i.0=0. |
main() { | |
auto int i=HIGH; | i.1=5. |
reset(i.1/2); | Функция reset вызывается с параметром i.1/2. Ее выполнение не затрагивает i.1. |
PRINT1(d,i.1); | |
reset(i.1=i.1/2); | Опять обращаются к reset со значением i.1/2. На этот раз побочным эффектом от вызова функции будет присваивание i.1 значения 2, а reset опять не повлияет на i.1. |
PRINT1(d,i.1); | |
i.1=reset(i.1/2); | Переменная i.1 получит значение, выдаваемое reset при обращении к ней с параметром i.1/2. Мы вставим в это место тело функции. |
int reset(1) | Тип значения, выдаваемого функцией, указывается в ее описании. Функция reset возвращает значение типа int. |
{ (int i=1;) | i.reset=1. Параметры функции можно рассматривать как инициированные локальные переменные. Мы выделили эти неявные присваивания с помощью скобок. |
i.reset= i.reset | i.reset=5. |
return (i.reset); | Функция reset возвращает целое 5; так что i.1=5. |
PRINT1(d,i.1); | |
workover(i.1) | Функции workover передается значение i.1; сама i.1 вызовом функции не затрагивается. Мы вставим здесь тело функции, так как оно содержит обращение PRINT1. |
workover(5) | Если не указано что-то другое, то функция возвращает значение типа int. |
{(int i=5;) | i.workover=5. |
i. workover=0*whatever | i.workover=0. |
PRINT1(d, i.workover); | |
return(i.workover); } | Функция workover возвращает 0, но обращающаяся к ней программа это игнорирует. |
PRINT1(d,i.1); } |