Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции_по_общей_информатике.doc
Скачиваний:
7
Добавлен:
01.07.2025
Размер:
8 Мб
Скачать
☆

Компиляция и интерпретация программ

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

Машинные языки исторически были первыми языками программирования. Программирование на них затруднительно ввиду того, что, во-первых, эти языки различны для каждого типа ЭВМ, во-вторых, они являются трудоемкими для боль­шинства пользователей по причине необходимости знания особенностей конкрет­ной ЭВМ и большого количества реализуемых ею операций (команд). Данные языки обычно используются для разработки системных программ, при этом чаще всего применяются специальные символические языки — Ассемблеры, близкие к соответствующим машинным языкам.

Человеку свойственно формулировать и решать задачи в выражениях более общего характера, чем команды ЭВМ. Поэтому с развитием программирования появились языки, ориентированные на достаточно высокий уровень абстракции при описании решаемой на ЭВМ задачи. Эти языки получили название языков высокого уровня. Их теоретическую основу составляют алгоритмические языки, например, Бейсик, Паскаль, Си, Фортран, PL/1 и др.

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

Интерпретатор — это программа, которая получает на своем входе исходную программу и по мере распознавания конструкций входного языка реализует дей­ствия, описываемые этими конструкциями.

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

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

  1. Стили и языки программирования.

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

Процедурное программирование

Процедурное (императивное) программирование является отражением архи­тектуры традиционных ЭВМ, которая была предложена фон Нейманом в 40-х го­дах. Теоретической моделью процедурного программирования служит алгорит­мическая система под названием «машина Тьюринга».

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

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

Процедурные языки характеризуются следующими особенностями:

  1. необходимостью явного управления памятью, в частности, описанием пере­менных;

  2. малой пригодностью для символьных вычислений;

  3. отсутствием строгой математической основы;

  4. высокой эффективностью реализации на традиционных (фон Неймановских) ЭВМ.

Одним из важнейших классификационных признаков процедурного языка являет­ся его уровень. Уровень языка программирования определяется семантической (смыс­ловой) емкостью его конструкций и степенью его ориентации на программиста. Язык программирования частично ликвидирует разрыв между методами решения различ­ного рода задач человеком и вычислительной машиной. Чем более язык ориентиро­ван на человека, тем выше его уровень. Дадим краткую характеристику реализован­ным на ПЭВМ языкам программирования в порядке возрастания их уровня.

Двоичный язык является непосредственно машинным языком. В настоящее время такие языки программистами практически не применяются.

Язык Ассемблера — это язык, предназначенный для представления в удобочита­емой символической форме программ, записанных на машинном языке. Он позво­ляет программисту пользоваться мнемоническими кодами операций, присваивать удобные имена ячейкам и областям памяти, а также задавать наиболее удобные схе­мы адресации.

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

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

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

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

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

Одна из наиболее существенных особенностей С состоит в нивелировании раз­личий между выражениями и операторами, что приближает его к функциональ­ным языкам. В частности, выражение может обладать побочным эффектом при­сваивания, а также может использоваться в качестве оператора. Нет также четкой

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

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

Basic (Beginners All-purpose Symbolic Instruction Code — многоцелевой язык символических инструкций для начинающих — Бэйсик) представляет собой про­стой язык программирования, разработанный в 1964 году для использования но­вичками. Он был разработан как простейший язык для непосредственного обще­ния человека с вычислительной машиной. Поэтому первоначально работа велась в интерактивном режиме с использованием интерпретаторов. В настоящее время для этого языка имеются также и компиляторы.

Согласно концепциям, заложенным в Basic, этот язык в смысле строгости и стройности является антиподом языка Pascal. В частности, в нем широко распро­странены различные правила умолчания, что считается плохим тоном в большин­стве языков программирования подобного типа.

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

Pascal (Паскаль) является одним из наиболее популярных среди прикладных программистов процедурных языков программирования, особенно для ПЭВМ. Раз­работанный в 1970 году швейцарским специалистом в области вычислительной техники профессором Н. Виртом язык назван в честь французского математика и по замыслу автора предназначался для обучения программированию. Однако язык получился настолько удачным, что стал одним из основных инструментов при­кладных и системных программистов при решении задач вычислительного и ин­формационно-логического характера. В 1979 году был подготовлен проект описа­ния языка — Британский стандарт языка программирования Pascal BS6192: 1982 г., который стал также и международным стандартом ISO 7185.

В языке Pascal реализован ряд концепций, рассматриваемых как основа «дис­циплинированного» программирования и заимствованных впоследствии разработ­чиками многих языков. Одним из существенных признаков языка Pascal является последовательная и достаточно полная реализация концепции структурного про­граммирования. Причем это осуществляется не только путем упорядочивания свя­зей между фрагментами программы по управлению, но и за счет структуризации данных. Кроме того, в языке реализована концепция определения новых типов данных на основе уже имеющихся. Этот язык, в отличие от языка С, является строго типизированным. Pascal характеризуется:

  • высоким уровнем;

  • широкими возможностями;

□ стройностью, простотой и краткостью;

□ строгостью, способствующей написанию эффективных и надежных про­грамм;

□ высокой эффективностью реализации на ЭВМ.

Pascal реализован на ЭВМ различных типов, но наиболее распространен и раз­вит для ПЭВМ. В настоящее время широко используются такие версии этого язы­ка для ПЭВМ как Borland Pascal и Turbo Pascal.

Функциональное программирование

Сущность функционального (аппликативного) программирования определена А. П. Ершовым как «...способ составления программ, в которых единственным дей­ствием является вызов функции, единственным способом расчленения программы на части является введение имени для функции, а единственным правилом компо­зиции — оператор суперпозиции функции. Никаких ячеек памяти, ни операторов присваиваниями циклов, ни, тем более, блок-схем, ни передачи управления».

Роль основной конструкции в функциональных языках играет выражение. К выражениям относятся скалярные константы, структурированные объекты, функ­ции, тела функций и вызовы функций. Функция трактуется как однозначное отобра­жение из Хп в X, где X — множество выражений.

Аппликативный язык программирования включает следующие элементы:

  • классы констант, которыми могут манипулировать функции;

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

  • правила построения новых функций из базовых;

  • правила формирования выражений на основе вызовов функций.

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

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

Первым таким языком был LISP (ЛИСП) (LISt Processing — обработка спис­ков), созданный в 1959 году. Цель его создания состояла в организации удобства обработки символьной информации. Существенная черта этого языка — унифи­кация программных структур и структур данных — все выражения записываются в виде списков.

Логическое программирование

Новую область — логическое, или реляционное, программирование — открыло появление языка PROLOG (Пролог) (PROgramming in LOGic, программирование в терминах логики). Этот язык был создан французским ученым А. Кольмероэ в 1973 году. В настоящее время известны и другие языки, однако наиболее развитым и распространенным языком логического программирования является именно Про­лог. Так, имеется свыше 15 различных его реализаций на ПЭВМ. Языки логическо­го программирования, в особенности Пролог, широко используются в системах ис­кусственного интеллекта, рассматриваемых в данном учебном пособии.

Центральным понятием в логическом программировании является отношение. Программа представляет собой совокупность определенных отношений между объектами (в терминах условий или ограничений) и цели (запроса). Процесс вы­полнения программы трактуется как процесс общезначимости логической фор­мулы, построенной из программы по правилам, установленным семантикой ис­пользуемого языка. Результат вычисления является побочным продуктом этого процесса. В реляционном программировании нужно только специфицировать фак­ты, на которых алгоритм основывается, а не определять последовательность ша­гов, которые требуется выполнить. Это свидетельствует о декларативности языка логического программирования. Она метко выражена в формуле Р. Ковальского: «алгоритм = логика + управление».

Языки логического программирования характеризуются:

  • высоким уровнем;

  • строгой ориентацией на символьные вычисления;

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

  • возможной логической неполнотой, поскольку зачастую невозможно выра­зить в программе определенные логические соотношения, а также невоз­можно получить из программы все выводы правильные.

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

Объектно-ориентированное программирование

Прототипом объектно-ориентированного программирования послужил ряд средств, входящих в состав языка SIMULA-67. Но в самостоятельный стиль онооформилось с появлением языка SMALLTALK, разработанного А. Кеем в 1972 году и первоначально предназначенного для реализации функций машинной гра­фики.

В основе объектно-ориентированного стиля программирования лежит понятие объекта, а суть его выражается формулой: «объект = данные + процедуры». Каж­дый объект интегрирует в себе некоторую структуру данных и доступные только ему процедуры обработки этих данных, называемые методами. Объединение дан­ных и процедур в одном объекте называется инкапсуляцией и присуще объектно-ориентированному программированию.

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

Программирование рассматриваемого стиля заключается в выборе имеющих­ся или создании новых объектов и организации взаимодействия между ними. При создании новых объектов свойства объектов могут добавляться или наследовать­ся от объектов-предков. В процессе работы с объектами допускается полимор­физм — возможность использования методов с одинаковыми именами для обра­ботки данных разных типов.

К наиболее современным объектно-ориентированным языкам программирова­ния относятся C++, Object Pascal и Java.

Язык C++ был разработан в начале 80-х годов Б. Страуструпом, сотрудником лаборатории Bell корпорации AT&T. Им была создана компактная компилирующая система, в которой за основу был взят язык С, дополненный элементами языков BCPL, Simula67 и Algol68. К июлю 1983 года появился язык «С с классами», а чуть позднее — C++. К 1990 году была выпущена третья версия языка C++, принятая комитетом ANSI в качестве исходного материала для его стандартизации.

Язык Object Pascal представляет собой объектно-ориентированное расшире­ние стандартного языка Pascal. Свое применение он получил в системе програм­мирования Delphi. Начиная с версии 7.0 в системе Delphi для разработки приложе­ний используется язык программирования Delphi, основу которого составляет язык Object Pascal.

В 1990 году сотрудник корпорации Sun Д. Гослинг на основе расширения C++ разработал объектно-ориентированный язык Oak, основным достоинством кото­рого было обеспечение сетевого взаимодействия различных по типу устройств. Новая интегрируемая в Internet версия языка, получила название Java. Первый броузер, который поддерживал язык Java, разработан программистом корпора­ции Sun П. Нафтоном и получил название HotJava. С января 1995 года Java полу­чает распространение в Internet.

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

Принципиальной разницей между Java и C++ является то, что первый из них является интерпретируемым, а второй — компилируемым. Синтаксис языков прак­тически полностью совпадает.

С точки зрения возможностей собственно объектно-ориентированных средств язык Java обладает рядом преимуществ перед языком C++. Так, язык Java демон­стрирует более гибкую и мощную систему инкапсуляции информации. Механизм наследования, реализованный в Java, обязывает к более строгому подходу к про­граммированию, что улучшает надежность и понимаемость кода. Язык же C++ обладает сложной, неадекватной и трудной для понимания системой наследова­ния. Возможности динамического связывания объектов одинаково хорошо пред­ставлены в обоих языках, однако, синтаксическая избыточность C++ заставляет и здесь отдать предпочтение языку Java.

В силу своей конструктивности идеи объектно-ориентированного программи­рования используются во многих универсальных процедурных языках. Так, на­пример, в состав интегрированной системы программирования на языке PASCAL (корпорации Borland International) версии 5.5, входит специальная библиотека объектно-ориентированного программирования Turbo Vision.

В последнее время многие программы, в особенности объектно-ориентирован­ные, реализуются как системы визуального программирования. Отличительной особенностью таких систем является мощная среда разработки программ из гото­вых «строительных блоков», позволяющая создать интерфейсную часть программ­ного продукта в диалоговом режиме, практически без кодирования программных операций. К числу объектно-ориентированных систем визуального программиро­вания относятся: Visual Basic, Delphi, C++ Builder и Visual C++.