Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Информатика конспект лекций_2012

.pdf
Скачиваний:
59
Добавлен:
28.03.2015
Размер:
6.29 Mб
Скачать

Синтаксическая диаграмма для данного оператора (рис. 72) выглядит следующим образом:

Рис. 72. Синтаксическая диаграмма для оператора for

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

где S1 и S2 – выражения, определяющие соответственно начальное и конечное значения параметра цикла.

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

Заголовок оператора повтора for определяет:

диапазон изменения значений управляющей переменной (параметра цикла) и одновременно число повторений оператора, содержащегося в теле цикла;

направление изменения значения параметра цикла (возрастание – to или убывание – downto).

При первом обращении к оператору for вначале вычисляются выражения S1, S2 и осуществляется присваивание

<параметр циклa>: = Sl.

После этого циклически повторяются следующие действия.

1.Проверяется условие <параметр цикла>:< = S2.

2.Если условие выполнено, то оператор for продолжает работу (выполняется оператор в теле цикла), если условие <параметр цикла>:< = = S2 не выполнено, то оператор for завершает работу, и управление

впрограмме передается на оператор, следующий за циклом.

3.Значение управляющей переменной изменяется на +1 (to) или -1 (downto) и далее с п. 1. Необходимо обратить внимание на то, что шаг

250

изменения управляющей переменной – единица.

На использование управляющей переменной (параметра цикла)

вцикле for налагаются следующие ограничения:

1)в качестве параметра должна использоваться простая переменная, описанная в текущем блоке;

2)управляющая переменная должна иметь дискретный тип;

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

4)в теле цикла запрещается явное изменение значения управляющей переменной (например, оператором присваивания);

5)после завершения оператора значение управляющей переменной становится неопределенным, если только выполнение оператора не было прервано оператором перехода.

251

ЛЕКЦИЯ 29. ТРАНСЛЯЦИЯ И ВЫПОЛНЕНИЕ ПРОГРАММЫ

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

Подготовка программы начинается с редактирования файла, содержащего текст программы, который имеет стандартное расширение для данного языка. Затем выполняется его трансляция, которая включает в себя несколько фаз: препроцессор, лексический, синтаксический, семантический анализ, генерация кода и его оптимизация. В результате трансляции получается объектный модуль – некий «полуфабрикат» готовой программы, который впоследствии участвует в ее сборке. Файл объектного модуля имеет стандартное расширение «.obj». Компоновка (сборка) программы заключается в объединении одного или нескольких объектных модулей программы и объектных модулей, взятых из библиотечных файлов и содержащих стандартные функции и другие полезные вещи. В результате получается исполняемая программа в виде отдельного файла (загрузочный модуль, программный файл) со стандартным расширением – «.exe», который затем загружается в память и выполняется.

Трансляция и ее фазы

Собственно трансляция начинается с лексического анализа программы. ЛЕКСИКА языка программирования – это правила «правописания слов» программы, таких, как идентификаторы, константы, служебные слова, комментарии. Лексический анализ разбивает текст программы на указанные элементы. Особенность любой лексики в том, что ее элементы представляют собой регулярные линейные последовательности символов. Например, ИДЕНТИФИКАТОР – это произвольная последовательность букв, цифр и символа «_», начинающаяся с буквы или «_».

СИНТАКСИС языка программирования – это правила составления предложений языка из отдельных слов. Такими предложениями являются операции, операторы, определения функций и переменных.

252

Особенностью синтаксиса является принцип вложенности (рекурсивность) правил построения предложений. Это значит, что элемент синтаксиса языка в своем определении прямо или косвенно в одной из его частей содержит сам себя. Например, в определении оператора цикла телом цикла является оператор, частным случаем которого является все тот же оператор цикла.

СЕМАНТИКА языка программирования – это смысл, который закладывается в каждую конструкцию языка. Семантический анализ – это проверка смысловой правильности конструкции. Например, если в выражении используется переменная, то она должна быть определена ранее по тексту программы, а из этого определения может быть получен ее тип. Исходя из типа переменной, можно говорить о допустимости операции с данной переменной.

ГЕНЕРАЦИЯ КОДА – это преобразование элементарных действий, полученных в результате лексического, синтаксического и семантического анализа программы, в некоторое внутреннее представление. Это могут быть коды команд, адреса и содержимое памяти данных либо текст программы на языке Ассемблера, либо стандартизованный промежуточный код (например, P-код). В процессе генерации кода производится и его оптимизация.

Модульное программирование, компоновка

Полученный в результате трансляции ОБЪЕКТНЫЙ МОДУЛЬ включает в себя готовые к выполнению коды команд, адреса и содержимое памяти данных. Но это касается только собственных внутренних объектов программы (функций и переменных). Обращение к внешним функциям и переменным, отсутствующим в данном фрагменте программы, не может быть полностью переведено во внутреннее представление и остается в объектном модуле в исходном (текстовом) виде. Но если эти функции и переменные отсутствуют, значит, они должны быть каким-то образом получены в других объектных модулях. Самый естественный способ получения – написать их на том же самом Си и оттранслировать. Это и есть принцип МОДУЛЬНОГО ПРОГРАММИРОВАНИЯ – представление текста программы в виде нескольких файлов, каждый из которых транслируется отдельно. С модульным программированием мы сталкиваемся в двух случаях:

-когда сами пишем модульную программу;

-используем стандартные библиотечные функции.

253

БИБЛИОТЕКА ОБЪЕКТНЫХ МОДУЛЕЙ – это файл (библиотечный файл), содержащий набор объектных модулей и собственный внутренний каталог. Объектные модули библиотеки извлекаются из нее целиком при наличии в них требуемых внешних функций и переменных и используются в процессе компоновки программы.

КОМПОНОВКА – это процесс сборки программы из объектных модулей, в ходе которой производится их объединение в исполняемую программу и связывание вызовов внешних функций и их внутреннего представления (кодов), расположенных в различных объектных модулях.

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

Сущность трансляции. Компиляция и интерпретация

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

КОМПИЛЯЦИЯ – это преобразование объектов (данных и операций над ними) с входного языка в объекты на другом языке для всей программы в целом с последующим выполнением полученной программы в виде отдельного шага.

ИНТЕРПРЕТАЦИЯ – это анализ отдельного объекта на входном языке с одновременным выполнением (интерпретацией).

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

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

254

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

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

-процессор и память любого компьютера (а в широком смысле,

ився программная среда, создаваемая операционной системой), являются ИНТЕРПРЕТАТОРОМ машинного кода;

-в практике построения трансляторов часто встречаются случаи, когда программа компилируется со входного языка на некоторый промежуточный уровень (внутренний язык), для которого имеется программный интерпретатор. Многие языковые системы программирования, называемые интерпретаторами, имеют фазу компиляции во внутренне представление, в ходе которой производится интерпретация.

Выходной язык компилятора может быть машинным языком для компьютера с другой архитектурой, нежели тот, в котором работает компилятор. Такой компилятор называется КРОСС-КОМПИЛЯ- ТОРОМ, а сама система программирования КРОСС-СИСТЕМОЙ. Такие системы используются для разработки программ в архитектурах, не имеющих собственных операционных систем, или систем программирования (контроллеры, управляющие микропроцессоры).

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

Создание слоя программной интерпретации для некоторого промежуточного языка в практике построения трансляторов обычно встречается при попытке обеспечить совместимость для имеющегося многообразия языков программирования, операционных систем, архитектур и т.д. То есть определяется некоторый внутренний промежуточный язык, достаточно простой, чтобы для него можно было написать интепретатор для всего имеющегося многообразия операционных систем или архитектур. Затем пишется одни (или несколько) компиляторов для одного (или нескольких) входных языков на этот промежуточный уровень. Приведем примеры такой стандартизации:

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

255

ционными системами был разработан универсальный внутренний язык (P-код). Для каждой такой архитектуры необходимо реализовать свой интерпретатор P-кода. При этом все разнообразие имеющихся компиляторов с языков высокого уровня на P-код может быть использовано без каких-либо изменений;

-язык программирования Java аналогично был разработан для обеспечения переносимости различных приложений в среде Internet.

Структура транслятора

Самое главное в процессе трансляции состоит в том, что он не является линейным, то есть последовательным преобразованием фрагмента программы одного языка на другой. На процесс трансляции одного фрагмента обязательно оказывают влияние другие фрагменты программы. Поэтому трансляция представляет собой несколько последовательных фаз анализа программы, на каждой из которой текст программы разделяется на все более «тонкие» компоненты, а информация о них группируется в некоторое внутреннее представление программы (деревья, таблицы). Затем или параллельно с этим процессом осуществляется синтез программы уже на выходном языке программирования, с использованиеминформации извнутреннегопредставления.

Отдельные фазы трансляции могут быть связаны между собой различным образом, через данные в памяти или через файл, что не меняет сущности процесса:

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

ипо ним формирует выходной файл с данными для следующей фазы;

-фазы трансляции вызывают одна другую в процессе обработки соответствующих языковых единиц. Синтаксический анализ является обычно центральным в такой структуре. То есть основной программой транслятора является синтаксический анализатор, который при анализе структурной единицы языка, называемой предложением (выражение, оператор, определение типа или переменной), вызывает лексический анализатор для чтения очередной лексической компоненты (идентификатора, константы), а по завершении разбора – семантическую процедуру, процедуры генерации кода или интерпретации. Из этой схемы выпадает только препроцессор, который обычно представляет собой независимую предварительную фазу трансляции.

256

ЛЕКЦИЯ 30. ЭВОЛЮЦИЯ ЯЗЫКОВ ПРОГРАММИРОВАНИЯ

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

К настоящему времени созданы десятки различных ЯП – от самых примитивных до близких к естественному языку человека. Чтобы разобраться во всем многообразии ЯП, нужно знать их классификацию, а также историю создания, эволюцию и тенденции развития.

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

Во-первых, ЯП является инструментом программиста для создания программ. Для создания хороших программ нужны хорошие ЯП. Поэтому одной из движущих сил эволюции ЯП является стремление разработчиков к созданию более совершенных программ.

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

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

257

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

В-четвертых, совершенствование самих ЭВМ приводит к необходимости создания языков, максимально реализующих новые возможности ЭВМ.

В-пятых, программы являются интеллектуальным продуктом, который нужно накапливать и приумножать. Но программы, как и технические изделия, обладают свойством морального старения, одной из причин которого является их зависимость от типа ЭВМ и операционной среды. С моральным старением программ борются путем их модернизации и выпуска новых версий, однако при высокой динамике смены типов ЭВМ и операционных сред разработчики могут только тем и заниматься, что модернизировать старые программы. Поэтому ЯП должен обеспечивать продолжительный жизненный цикл программы, и стремление к этому является пятой движущей силой развития ЯП.

Известно, что первым программистом была женщина – леди Ада Лавлейс, дочь лорда Байрона. Она разрабатывала программы для одного из первых механических компьютеров, созданного в начале XIX в. английским ученым Чарльзом Беббиджом. Однако настоящее программирование, в современном понимании, началось с момента создания первой электронной вычислительной машины. Но тем не менее имя этой замечательной женщины – Ada – присвоено одному из самых мощных современных ЯП, который является базовым для министерства обороны США.

Первые ЭВМ, созданные человеком, имели небольшой набор команд и встроенных типов данных, но позволяли выполнять программы на машинном языке. Машинный язык (МЯ) – единственный язык, понятный ЭВМ. Он реализуется аппаратно: каждую команду выполняет некоторое электронное устройство. Программа на МЯ представляет собой последовательность команд и данных, заданных в цифровом виде. Например, команда вида 1А12 в 16-ричном виде или 0001101000010010 в двоичном виде означает операцию сложения (1А) содержимого регистров 1 и 2.

Данные на МЯ представлены числами и символами. Операции являются элементарными и из них строится вся программа. Ввод программы в цифровом виде производился непосредственно в память

258

с пульта ЭВМ либо с примитивных устройств ввода. Естественно, что процесс программирования был очень трудоемким, разобраться в программе даже автору было довольно сложно, а эффект от применения ЭВМ был низким. Этот этап в развитии ЯП показал, что программирование является сложной проблемой, трудно поддающейся автоматизации, но именно программное обеспечение определяет в конечном счете эффективность применения ЭВМ. Поэтому на всех последующих этапах усилия направлялись на совершенствование интерфейса между программистом и ЭВМ – языка программирования.

Стремление программистов оперировать не цифрами, а символами, привело к созданию мнемонического языка программирования, который называли ассемблером, мнемокодом, автокодом. Этот язык имел определенный синтаксис записи программ, в котором, в частности, цифровой код операции был заменен мнемоническим кодом. Например, команда сложения записывалась в виде AR 1,2 что означает сложение (Addition) типа регистр-регистр (Register) для реги-

стров

1

и 2. В таком виде программа имела более удобочитаемую форму, но ее не понимала ЭВМ. Поэтому понадобилось создать специальную программу-транслятор, которая преобразовывала программу с языка ассемблера на МЯ. Эта проблема потребовала, в свою очередь, глубоких научных исследований и разработки различных теорий, например, теории формальных языков, которые легли в основу создания трансляторов. Практически любой класс ЭВМ имеет свой язык ассемблера. На сегодняшний день язык ассемблера используется для создания системных программ, использующих специфические аппаратные возможности данного класса ЭВМ.

Следующий этап характеризуется созданием языков высокого уровня (ЯВУ). Эти языки являются универсальными (на них можно создавать любые прикладные программы) и алгоритмически полными, имеют более широкий спектр типов данных и операций, поддерживают технологии программирования. На этих языках создается неисчислимое множество различных прикладных программ.

Принципиальными отличиями ЯВУ от языков низкого уровня являются:·

·использование переменных;

·возможность записи сложных выражений;

259