Обзор языков программирования
Компьютерная программа представляет собой логически упорядоченную последовательность команд, предназначенных для управления компьютером. Процессор компьютера — это большая интегральная схема. Все данные и команды он получает в виде электрических сигналов. В двоичном коде наличие сигнала описывается понятием «1», а его отсутствие - понятием «О». Команды, обрабатываемые процессором, можно интерпретировать как ряд чередующихся определенным образом единиц и нулей, то есть любая команда преобразуется в двоичное число. Таким образом, процессор исполняет программы, представляющие собой последовательность чисел и называемые машинным кодом.
Писать программы в машинных кодах очень сложно, причем с ростом размера программы эта задача усложняется. В компьютерах первого поколения использовались программы, написанные в машинных кодах, причем для каждого компьютера существовал свой собственный машинный код. Числовая кодировка команд, адресов ячеек и обрабатываемых данных, зависимость вида программы от ее места в памяти не давали возможность следить за смыслом программы. Это во многом ограничивало область применения компьютеров первого поколения.
В тот период (начало 50-х гг.) средства программирования и программное обеспечение только зарождались и были еще не развиты. Для того чтобы сделать программу читабельной и иметь возможность следить за ее смысловой структурой, придумали символический язык ассемблер, близкий к машинному (конец 50-х -начало 60-х гг.), в котором появилось понятие переменной. Ассемблер стал первым полноценным языком программирования. Благодаря этому заметно уменьшилось время разработки и возросла надежность программ. Для записи кодов операций и обрабатываемой информации в ассемблере используются стандартные обозначения, позволяющие записывать числа и текст в общепринятом виде, для кодов команд приняты мнемонические обозначения. Для обозначения величин, размещаемых в памяти, можно применять имена. После ввода программы ассемблер сам заменяет символические имена на адреса памяти, а символические коды команд на числовые. Использование ассемблера сделало процесс программирование более наглядным. Дальнейшее развитие этой идеи привело к созданию языков программирования высокого уровня, в которых длинные и сложные последовательности машинных кодов были заменены одним единственным обозначающим их словом - операторы.
Сегодня практически все программы создаются с помощью языков программирования. Теоретически программу можно написать и на естественном языке (говорят: программирование на метаязыке), но из-за неоднозначности естественного языка автоматически перевести такую программу в машинный код пока невозможно.
Языки программирования — это формальные искусственные языки. Как и естественные языки, они имеют алфавит, словарный запас, грамматику и синтаксис, а также семантику.
Алфавит — разрешенный к использованию набор символов, с помощью которого могут быть образованы слова и величины данного языка.
Словарный состав или лексика языка - это совокупность употребляемых в нем слов, т.е. правильных слов данного языка.
Грамматика - это конечная система правил, определяющих язык.
Грамматика определяет способы построения изменения и сочетания слов.
Синтаксис — система правил, определяющих допустимые конструкции языка программирования из букв алфавита.
Семантика - система правил однозначного толкования каждой языковой конструкции, позволяющих производить процесс обработки данных.
Взаимодействие синтаксических и семантических правил определяет основные понятия языка, такие как операторы, идентификаторы, константы, переменные, функции, процедуры и т.д. В отличие от естественных, язык программирования имеет ограниченный запас слов (операторов) и строгие правила их написания, а правила грамматики и семантики, как и для любого формального языка, явно однозначно и четко сформулированы.
Языки программирования, ориентированные на команды процессора и учитывающие его особенности, называют языками низкого уровня. «Низкий уровень» не означает неразвитый, имеется в виду, что операторы этого языка близки к машинному коду и ориентированы на конкретные команды процессора.
Языком самого низкого уровня является ассемблер. Программа, написанная на нем, представляет последовательность команд машинных кодов, но записанных с помощью символьных мнемоник. С помощью языков низкого уровня создаются компактные оптимальные программы, так как программист получает доступ ко всем возможностям процессора. С другой стороны, при этом требуется хорошо понимать устройство компьютера, а использование такой программы на компьютере с процессором другого типа невозможно. Такие языки программирования используются для написания небольших системных приложений, драйверов устройств, модулей стыковки с нестандартным оборудованием, когда важнее компактность, быстродействие, прямой доступ к аппаратным ресурсам.
Языки программирования, имитирующие естественные, обладающие укрупненными командами, ориентированные «на человека», называют языками высокого уровня. Чем выше уровень языка, тем ближе структуры данных и конструкции, использующиеся в программе, к понятиям исходной задачи. Особенности конкретных компьютерных архитектур в них не учитываются, поэтому исходные тексты программ легко переносимы на другие платформы, имеющие трансляторы этого языка. Разрабатывать программы на языках высокого уровня с помощью понятных и мощных команд значительно проще; число ошибок, допускаемых в процессе программирования, намного меньше. В настоящее время насчитывается несколько сотен таких языков (без учета их диалектов).
Таким образом, языки программирования высокого уровня, ориентированные на решение больших содержательных прикладных задач, являются аппаратно-независимыми и требуют использования соответствующих программ-переводчиков для преобразования текста программы в машинный код, который в итоге и обрабатывается процессором.
Язык высокого уровня «непонятен» компьютеру, поэтому существуют специальные программы-трансляторы, переводящие операторы языка высокого уровня в машинные коды.
Существуют два типа программ-трансляторов: компилятор и интерпретатор.
Компилятор работает сразу со всем исходным модулем, формируя на его основе загрузочный модуль, т. е. исполняемый файл, готовый для выполнения на компьютере. Программа в виде загрузочного модуля выполняется независимо от исходного модуля.
Интерпретатор работает с исходным модулем по шагам. Он разбирает (интерпретирует) каждый оператор исходного модуля и выполняет его. В режиме интерпретации проще отлаживать программу, однако программа работает значительно медленнее, чем скомпилированная программа.
Существенным шагом по снижению трудоемкости создания программ при повышении их качества, надежности и возможности использования в массовом порядке явилось структурированное программирование. Его основные принципы следующие:
• нисходящее программирование;
• модульное программирование;
• структурное программирование;
• структурный контроль.
Нисходящее программирование основано на иерархическом подходе к решению задач и используется на начальной стадии процесса разработки решения задачи. При этом составляется иерархическая модель объекта, выбираются функция, степень детализации.
Иерархическая модель строится по следующим правилам:
- каждый модуль может быть связан только с одним модулем верхнего уровня и с несколькими модулями нижнего уровня;
- для каждого модуля нижнего уровня имеется выход в модуль верхнего уровня;
- связи между модулями организуются сверху вниз;
- обращение к одному модулю возможно несколько раз, при этом он изображается один раз и оформляется как подпрограмма.
Модульное программирование предполагает независимое программирование каждого модуля, начиная с верхнего уровня иерархии. При осуществлении тестирования модулей верхнего уровня на модули нижнего уровня ставится «заглушка», чаще всего в виде оператора печати. Модули добавляются по одному. После окончания разработки каждого модуля тестируется весь комплекс в целом.
Модульное программирование позволяет существенно сократить время, необходимое на отладку программ.
Структурное программирование — это процесс программирования на алгоритмическом языке с использованием определенных конструкций. При этом следует соблюдать следующие правила:
- любая программа составляется на базе основных алгоритмических структур трех видов: линейного, разветвляющегося, циклического;
- между этими структурами производится передача управления только вперед — от более высокого уровня иерархии к более низкому;
- запрещается использовать команду переходов «GOTO». Структурное программирование используется в основном для программирования отдельных модулей.
Структурный контроль используется при решении сложных многомодульных задач. Группе специалистов-сотрудников выдаются рабочие материалы по разрабатываемой задаче, они обсуждают и вносят замечания, которые разработчики должны реализовать.
Свойства языков программирования:
Понятность
Понятность (удобочитаемость) конструкций языка — это свойство, обеспечивающее легкость восприятия программ человеком.
Надежность
Под надежностью понимается степень автоматического обнаружения ошибок, которое может быть выполнено транслятором или операционной средой, в которой выполняется программа.
Гибкость
Гибкость языка программирования проявляется в том, сколько возможностей он предоставляет программисту для выражения всех операций, которые требуются в программе, не заставляя его прибегать к вставкам ассемблерного кода или различным ухищрениям.
Простота
Простота языка обеспечивает легкость понимания семантики языковых конструкций и запоминания их синтаксиса.
Естественность
Язык должен содержать такие структуры данных, управляющие структуры и операции, а также иметь такой синтаксис, которые позволяли бы отражать в программе логические структуры, лежащие в основе реализуемого алгоритма.
Мобильность
Язык, независимый от аппаратуры, предоставляет возможность переносить программы с одной платформы на другую с относительной легкостью. Это позволяет распределить высокую стоимость программного обеспечения на ряд платформ.
Стоимость
Суммарная стоимость использования языка программирования складывается из нескольких составляющих. В нее входят:
• стоимость обучения языку;
• стоимость создания программы;
• стоимость трансляции программы;
• стоимость выполнения программы;
• стоимость сопровождения программы.
Языки программирования или алгоритмические языки классифицируются: по степени их зависимости от вычислительной машины; по ориентации на сферу применения; по специфике организационной структуры языковых конструкций и т.п. (рис. 6.1),
Рис. 6.1. Классификация языков программирования
Любую систему обозначений и согласованную с ней систему понятий, которую можно использовать для описания алгоритмов и структур данных, в первом приближении можно считать языком программирования.
Знание концептуальных основ языков программирования с точки зрения использования и реализации базовых языковых конструкций позволит:
- более обоснованно выбрать язык программирования для реализации конкретного проекта;
- разрабатывать более эффективные алгоритмы;
- систематически пополнять набор полезных языковых конструкций;
- ускорить изучение новых языков программирования;
- использовать полученные знания как методологическую основу для разработки новых языков программирования;
- получить базовые знания, необходимые для разработки трансляторов для языков программирования, поддерживающих разные вычислительные модели.
Все эти языки называются еще и формальными. Нас более всего интересуют алгоритмические языки, к которым относятся все известные языки программирования.
Для решения задачи на ЭВМ составляется алгоритм, обеспечивающий выполнение всех необходимых действий для получения искомых результатов. Этот алгоритм описывается средствами формального языка, понятного ЭВМ - языка программирования.
К таким средствам относятся элементы языка - символы, цифры, специальные знаки, а также правила составления операторов для описания действий по вводу - выводу и распределению памяти, управлению ветвлением и организацией циклов, обращениям ко внешним устройствам, контролю и отладке отдельных фрагментов и программы в целом, формированию выходных документов и так далее. Каждая ЭВМ имеет свой собственный язык кодов команд, называемый машинным, который обеспечивает непосредственное выполнение любой последовательности машинных операций. Практически компьютер выполняет программы, записанные только на машинном языке. Однако с помощью дополнительных средств (системных программ) реализуются многоуровневые переводы (трансляции) текстов программ с различных языков программирования на язык ЭВМ. Эти языки программирования в отличие от машинных, называются языками высокого уровня, они мало зависят от особенностей конфигурации конкретной ЭВМ, то есть эти языки являются машинно-независимыми.
В языке символического кодирования (ЯСК), в отличие от машинного, цифровые коды заменены буквенными или буквенно-цифровыми (мнемоническими) обозначениями. Это облегчает работу по составлению программы и позволяет автоматизировать действия, связанные с размещениями программы и данных в памяти ЭВМ. Каждой команде языка символического кодирования при трансляции соответствует одна машинная команда. Такие языки называются мнемокодами или языками ассемблеров.
Язык более высокого уровня - макроязык - включает наряду с мнемоническими обозначениями машинных команд отдельные макрокоманды, которые при трансляции заменяются группами команд машинного языка (подпрограммами). Это сокращает запись исходной программы и упрощает программирование, так как исключаются записи часто повторяющихся фрагментов программы. В настоящее время все языки ассемблерного типа допускают использование макросредств, то есть являются макроассемблерами.
Машинно-ориентированные языки содержат все необходимые средства для программирования любых задач. Однако они применяются, когда требуется создать особо быстродействующие программы при минимальных объемах используемой памяти. В частности, на этих языках пишут программы управления устройствами ЭВМ и предварительной обработки данных.
Большинство производственных задач решают с помощью программ, написанных на процедурно - ориентированных языках. Средства этих языков позволяют наиболее просто описать часто встречающиеся фрагменты действий в соответствующих задачах. Процедурно-ориентированные языки предполагают знания пользователя в области математических (численных) методов и основ алгоритмизации (базовый язык для научно-технических расчетов ФОРТРАН, БЕЙСИК (персональные ЭВМ - основной), современный ПАСКАЛЬ).
В процессе развития созданы многоцелевые (универсальные) языки программирования, объединяющие основные средства и возможности многих процедурно - ориентированных языков, например: ПЛ/1 -используемый для решения задач обработки экономической и научно-технической информации, задач управления объектами и т.п.; язык АДА - многоцелевой стандартный язык, способный заменить множество других языков и на длительный период обеспечить разработку и совершенствования программ обеспечения; язык МОДУЛА - объединяет средства и особенности . машинно-ориентированных и процедурно - ориентированных языков; включает средства для написания подпрограмм управления устройствами, управления потоками сообщений, для чего традиционно использовались языки ассемблерного типа.
Для пользователей, не имеющих специальной подготовки, но нуждающихся в оперативном использовании ЭВМ для решения стереотипных задач, разрабатываются специальные проблемно - ориентированные языки(непроцедурные), которые не требуют подробной записи алгоритма решения задачи. На таком языке лишь формулируется задача и указывается последовательность подзадач из готового набора с указанием исходных данных и форм требуемых документов. Специальные средства программы-генераторы из готовых блоков автоматически формируют программу для решения поставленной задачи. Эти языки ещё более высокого уровня, т.е. удалены от машины более, чем процедурно-ориентируемые языки. К ним относятся языки для задания и обработки таблиц данных при решении экономических задач, а также языки моделирования сложных систем СИМУЛА, НЕДИС и другие (СИМСКРИПТ).
Граница между проблемно - и процедурно - ориентированными языками очерчена не очень четко (условно) - ЛИСП, ПРОЛОГ.