Учебное пособие по дисциплине Разработка языков программирования высокого уровня
Скачать 1.74 Mb.
|
2.5 Связывание переменной с типом данныхСуществует три способа связывания типа с переменной: Статическоесвязывание. Реализуется с помощью: операторов объявления типов; правил объявления типа, принятых при разработке языка. Большинство ЯПВУ требуют явного объявления, т.е. наличие в составе языка операторов объявления типа переменной. Однако в таких ЯП, как FORTRAN, PL\1, Бейсик есть и неявные соглашения. Например, переменные , имена которых начинаются с букв i, j, k, l, m, n считаются типа integer, хотя неявные объявления способствуют возникновению ошибок. Статическое связывание обычно реализуется на стадии компиляции, поэтому оно поддерживает надежность языка программирования (и в этом основное преимущество статического связывания). Динамическоесвязывание. При динамическом связывании при объявлении переменной ее тип не указывается. Определение типа и его связывание с ней происходит при присвоении переменной значения. Например, в языках APL, SNOBOL4 существует оператор LIST 10.3 4.6 16.7 , который загрузит в переменную массив из 3-х реальных чисел и она станет массивом реальных чисел. Но, если ниже в программе имеется оператор LIST ← 30 то он изменит тип переменной на целый. Преимущества динамического способа заключаются в том, что обеспечивается значительная гибкость программирования: в одни и те же переменные в рамках одной и той же программы могут загружаться и обрабатываться данные различных типов (пример: алгоритм обработки таблицы данных, в которую один раз введены данные символьного типа; другой – числового). Однако такой способ имеет существенные недостатки: В силу отсутствия статического контроля типов, может случиться ситуация, когда неверные типы в правой части оператора присваивания не могут быть обнаружены ни при компиляции, ни при выполнении. Например: пусть X, Y – целые переменные, А – массив, пусть в программе вместо X = Y по ошибке записали X = A, тогда тип статическим связывании компилятор обнаружит такую ошибку. Сложная внутренняя реализация. В силу того, что проверка типов, распределение памяти делается только на этапе выполнения, каждая переменная должна иметь дескриптор для запоминания текущего типа. Кроме ого, ячейка для переменной должна быть динамического размера, поскольку значения различных типов требуют различных типов памяти. Обычно реализуется через интерпретатор, т.к. сложность динамического связывания требует значительных затрат времени, его использование целесообразно только при таком сборе реализации языка. 3. Логический вывод типа. Реализован в языке ML, который поддерживает и функциональное, и императивное программирование. Он использует механизм логического вывода типа. Например, в операторе с=3.14*r*r константа 3.14 определяет тип переменных r и с, если константы нет, то тип не определён. 2.5 Время жизни переменной.Время жизни переменной – это время, в течение которого переменная связана с ячейкой оперативной памяти. Размещение переменной в памяти предполагает: - Сопоставление реального адреса с именем переменной; - Занесение в эту ячейку конкретного значения. Удаление из памяти предполагает открепление адреса ячейки ОП от имени переменной. С точки зрения времени жизни, переменные могут быть: Статические, связываются с ячейкой на стадии компиляции и остаются связанными с той же ячейкой до конца выполнения программы (глобальные); Достоинства: эффективная прямая адресация; при выполнении программы не затрачивается время на размещение и удаление из памяти. Недостатки: уменьшается гибкость программирования; не поддерживаются рекурсии; невозможность совместного использования одной и той же ячейки. В языках FORTRAN-1, -2, -4 все переменные были статическими. В языках C, C++, Java реализовано гибкое управление памятью посредством специальных модификаторов. Например, для объявления статических переменных существует модификатор static. Динамические. Это безымянные ячейки из, так называемой, <<кучи>>, размещаемые и удаляемые с помощью явных команд периода выполнения, которые определяются программистом. При этом связывание с типом – статическое. Обращаться к таким переменным возможно только с помощью указателей и специальных функций. Например, в языке С, такими функциями являются malloc(), для распределения памяти и free() для удаления. Пример 4. int *intnode; /*intnode – указатель*/ intnode = malloc() /*свясзывает ячейку – помещает адрес ячейки в указатель*/ free(intnode); /* освобождает ячейку */ Явные динамические переменные часто используются в таких динамических структурах как связные списки и деревья, которым необходимо расти и\или сокращаться во время выполнения программы. Недостатки: корректное использование указателей и ссылок требует от программиста высокого профессионализма. Автоматические – “живут” внутри блока или программы, размещаются в особом разделе оперативной памяти – стеке – при обращении к подпрограмме и удаляются из памяти при завершении работы. Связывание автоматической переменной с типом происходит статически при компиляции на основе оператора объявления. Связывание с памятью – при выполнении программы. Позволяют использовать рекурсии, т.к. рекурсивным подпрограммам требуется некоторая локальная память, чтобы каждая активная копия рекурсивной подпрограммы имела свою версию локальных параметров. Недостатки: существенные затраты времени на размещение и удаление переменных на стадии выполнения программы. Неявные динамические – это переменные, размещение которых происходит при загрузке в них конкретных значений. Преимущества: гибкость при использовании оперативной памяти, т.к.в разные моменты времени можно использовать одну и ту же ячейку для разных типов данных. Недостатки: атрибуты таких переменных, в том числе, типы, диапазоны индексов массивов и т.п., определяются в динамическом режиме, поэтому необходимо формировать и поддерживать дескриптор, что требует существенных временных затрат. Кроме того, использование неявных динамических переменных влечёт высокую ненадёжность программы. |