Здесь знаком & обозначена операция вычисления адреса. Видно, что в дереве появляется элемент, которого не было явно в
исходной строке – число элементов. Обход дерева даст результат: a b i 1 + j 3 & + c * 1.3 +. Разумеется, чтобы получить кор-
ректный алгоритм перевода (или построения дерева), необходимо учитывать приоритеты квадрат-
ных скобок и запятой, а также правильно определить соответствующие действия. Для записи ус-
ловного оператора понадобится возможность разметки дерева, и операции условного и безуслов-
ного перехода. Обозначим условный переход по false как ?, и безусловный переход как ->. Тогда
дерево для выражения if A then B else C будет выглядеть следующим образом:
Условный переход имеет 2 операнда: условие, и метка, куда выполняется переход, если условие
ложно. Безусловный переход имеет один операнд. Результат записи будет следующий:
A m1 ? B m2 -> C. С учетом меток запись приобретет вид: A m1 ? B m2 -> m1: C m2:
Распределение памяти – это процесс, который ставит в соответствие лексическим единицам исходной программы адрес,
размер и атрибуты области памяти, необходимой для этой лексической единицы. Исходными данными служит, как правило,
таблица идентификаторов и декларативная часть программы (область описаний). Поскольку декларативная часть может явно
не присутствовать, и могут существовать дополнительные правила для описания констант и переменных, распределение па-
мяти выполняется после семантического анализа. Современные компиляторы работают не с абсолютными, а с относитель-
ными адресами памяти. По роли области памяти в результирующей программе она бывает глобальная и локальная. Гло-
бальная область памяти выделяется один раз при инициализации результирующей программы и действует все время выпол-
нения результирующей программы. Как правило, может быть доступна из любой части программы. Локальная область памя-
ти выделяется в начале выполнения некоторого фрагмента результирующей программы и может быть освобождена по за-
вершении этого фрагмента. Доступ к этой памяти запрещен за пределами данного фрагмента. По способу распределения
область памяти бывает статическая или динамическая. Статическая область памяти – это память, размер которой известен
на этапе компиляции. Поэтому компилятор всегда может выделить эту область памяти и связать ее с соответствующим эле-
ментом. Для статической памяти компилятор порождает некоторый адрес. В этом случае говорят о статическом связыва-
нии области памяти и лексической единицы языка. Для динамической памяти размер на этапе компиляции неизвестен. Он
станет известен в процессе выполнения программы. Поэтому для такой памяти компилятор порождает фрагмент кода, кото-
рый отвечает за ее распределение. В этом случае происходит динамическое связывание. Динамическая память может рас-
пределяться разработчиком программы или компилятором автоматически. В первом случае разработчик непосредственно
использует соответствующие функции, во втором – разработчик использует типы данных, операции над которыми предпо-
лагают перераспределение памяти, например, строки, динамические массивы и многие операции над объектами, и память
распределяется компилятором автоматически. Можно выделить автоматическую память – когда распределение памяти
планируется при компиляции, а выделяется и освобождается при выполнении программы. Многие компиляторы используют
специальный менеджер памяти, который при первом же требовании на выделение памяти запрашивает у ОС область памяти
значительного большего объема, а при последующих запросах он самостоятельно выделяет память из этого блока, и только
при невозможности этого вновь обращается к ОС. Менеджер памяти может обладать функциями сборщика мусора – поиска
и освобождения фрагментов, которые заняты, но не используются. При использовании менеджера памяти сокращается число
обращений к ОС, что несколько увеличивает быстродействие, кроме того, сокращается фрагментация оперативной памяти.
Код менеджера либо включается в код результирующей программы либо поставляется в виде динамически подгружаемой
библиотеки.
Размер памяти, необходимый для лексической единицы скалярного (базового) типа, считается заранее известным. К сожале-
нию, не удается полностью исключить зависимость результирующей программы от архитектуры вычислительной системы.
Для более сложных структур используются правила, определяемые семантикой этих структур. Для массивов это произведе-
ние числа элементов на размер памяти для одного элемента, для структур – сума размеров всех полей, для объединений –
размер максимального поля и т.д. Архитектура современных систем позволяет выполнять обработку данных эффективнее,
если адрес, по которому выбираются данные, кратен 2,4,8,16 байтам. Компиляторы могут использовать это свойство, как
правило, опционально.
Дисплей памяти процедуры – это область данных, доступных для обработки в этой процедуре. Он включает следующие
составляющие: глобальные данные всей программы, формальные аргументы процедуры, локальные данные процедуры. Ад-
рес возврата – это адрес того фрагмента кода результирующей программы, куда должно быть передано управление после
завершения данной процедуры. Процедура должна работать со своими данными однотипным образом вне зависимости от
того, откуда она была вызвана. Современные системы ориентированы как правило, на стековую организацию дисплея па-
мяти процедуры. Она основана на том, что для хранения параметров процедур и функций , их локальных переменных и ад-
реса возврата в результирующей программе выделяется одна на всю программу специальная область памяти, организованная
в виде стека. Этот стек называется стеком параметров. Объектный код процедуры адресуется к параметрам и локальным
переменным по смещению относительно вершины стека. Такой подход значительно упрощает и ускоряет выполнение вызо-
вов при стековой организации дисплея памяти процедуры. Недостатки, присущие этой схеме – невозможно точно оценить
необходимый размер стека, кроме того нет стандартного механизма реализации дисплея памяти процедуры. Так, параметры
могут помещаться в стек в прямом или обратном порядке. Извлекаться из стека они могут либо в момент возврата из проце-
дуры либо непосредственно после возврата. Так, в С параметры помещаются в обратном порядке и извлекаются после воз-
врата из функции, а в Pascal – в прямом порядке и извлекаются в момент возврата из процедуры. Кроме этого, часть пара-
метров могут передаваться в регистрах процессора. Эти вопросы становятся важны, если необходимо связать код, скомпи-
лированный на разных языках или компиляторах.
Исключительная ситуация – это нештатная ситуация, возникающая в ходе выполнения программы, предусматривающая,
что в момент ее возникновения выполнение программы будет прервано и управление будет передано специальному обра-
ботчику. По умолчанию весь код исходной программы помещается компилятором внутрь одного блока обработки исключи-
тельной ситуации, при этом компилятор сам порождает соответствующий код обработчика. Все современные компиляторы