1.2. Процедурные языки
Fortran
Первым языком программирования, который значительно превзошел уровень языка ассемблера, стал Fortran. Он был разработан в 1950-х годах группой специалистов фирмы IBM во главе с Джоном Бекусом и предназначался для абстрактного описания научных вычислений. Fortran встретил сильное противодействие по тем же причинам, что и все последующие предложения абстракций более высокого уровня, а именно из-за того, что большинство программистов полагало, что сгенерированный компилятором программный код не может быть лучше написанного вручную на языке ассемблера.
Подобно большинству первых языков программирования, Fortran имел серьезные недостатки в деталях самого языка, и, что важнее, в нем отсутствовала поддержка современных концепций структурирования модулей и данных. Сам Бекус, оглядываясь назад, говорил:
Мы просто придумывали язык по мере его осмысления. Мы расценивали проектирование языка не как трудную задачу, а просто как прелюдию к реальной проблеме: проектированию компилятора, который мог бы генерировать эффективные программы.
Однако преимущества абстракции быстро покорили большинство программистов: разработка программ стала более быстрой и надежной, а их машинная зависимость уменьшилась из-за абстрагирования от регистров и машинных команд. Поскольку самыми первыми на компьютерах рассчитывались научные задачи, Fortran стал стандартным языком в науке и технике, и только теперь на смену ему приходят другие языки. Fortran был неоднократно модернизирован (1966,1977,1990) с тем, чтобы адаптировать его к требованиям современных программных разработок.
Cobol и PL/1
Язык Cobol был разработан в 1950-х для обработки коммерческих данных. Он создавался комитетом, состоящим из представителей Министерства Обороны США, производителей компьютеров и коммерческих организаций типа страховых компаний. Предполагалось, что Cobol — это только временное решение, необходимое, пока не создан лучший проект; однако язык быстро стал самым распространенным в своей области (как Fortran в науке), причем по той же самой причине: он обеспечивал естественные средства выражения вычислений, типичных для своей области. При обработке коммерческих данных необходимо делать относительно простые вычисления для большого числа сложных записей данных, а по возможностям структурирования данных Cobol намного превосходит алгоритмические языки типа Fortran или С.
IBM позже создала язык PL/1, универсальный, обладающий всеми свойствами языков Fortran, Cobol и Algol. PL/1 заменил Fortran и Cobol на многих компьютерах IBM, но этот язык очень широкого диапазона никогда не поддерживался вне IBM, особенно на мини- и микроЭВМ, которые все больше и больше используются в организациях, занимающихся обработкой данных.
Algol и его потомки
Из ранних языков программирования Algol больше других повлиял на создание языков. Разработанный международной группой первоначально для общих и научных приложений, он никогда не достигал такой популярности, как Fortran, поскольку не имел той поддержки, которую Fortran получил от большинства производителей компьютеров. Описание первой версии языка Algol было опубликовано в 1958 г.; пересмотренная версия, Algol 60, широко использовалась в компьютерных научных исследованиях и была реализована на многих машинах, особенно в Европе. Третья версия языка, Algol 68, пользовалась влиянием среди теоретиков по языкам, хотя никогда широко не применялась.
От языка Algol произошли два важных языка: Jovial, который использовался Военно-воздушными силами США для систем реального времени, и Simula, один из первых языков моделирования. Но, возможно, наиболее известным его потомком является Pascal, разработанный в конце 1960-х Никлаусом Виртом. Целью разработки было создание языка, который можно было бы использовать для демонстрации идей объявления типов и контроля их соответствия. В последующих главах мы докажем, что эти концепции относятся к наиболее важным, когда-либо предлагавшимся в проектировании языков.
Как язык практического программирования Pascal имеет одно большое преимущество и один большой недостаток. Первоначальный компилятор языка Pascal был написан на самом языке Pascal и, таким образом, мог быть легко перенесен на любой компьютер. Язык распространялся быстро, особенно на создаваемых в то время мини- и микроЭВМ. К сожалению, как язык, Pascal слишком мал. Стандартный Pascal вообще не имеет никаких средств для деления программы на модули, хранящиеся в отдельных файлах, и поэтому не может использоваться для программ объемом больше нескольких тысяч строк. Компиляторы Pascal, используемые на практике, поддерживают декомпозицию на модули, но никаких стандартных методов для этого не существует, так что большие программы непереносимы. Вирт сразу понял, что модули являются необходимой частью любого практического языка, и разработал язык Modula. Modula (теперь в версии 3, поддерживающей объектно-ориентированное программирование) — популярная альтернатива нестандартным «диалектам» языка Pascal.
С
Язык С был разработан в начале 1970-х Деннисом Ричи, сотрудником Bell Laboratories, как язык реализации операционной системы UNIX. Операционные системы традиционно писали на ассемблере, поскольку языки высокого уровня считались неэффективными. Язык С абстрагируется от деталей программирования, присущих ассемблерам, предлагая структурированные управляющие операторы и структуры данных (массивы и записи) и сохраняя при этом всю гибкость ассемблерного низкоуровневого программирования (указатели и операции на уровне битов).
Так как система UNIX была легко доступна для университетов и написана на переносимом языке, а не на языке ассемблера, то она быстро стала популярна в академических и исследовательских учреждениях. Когда новые компьютеры и прикладные программы выходили из этих учреждений на коммерческий рынок, вместе с ними распространялись UNIX и С.
Язык С проектировался так, чтобы быть близким к языку ассемблера, и это обеспечивает ему чрезвычайную гибкость; но проблема состоит в том, что эта гибкость обусловливает чрезвычайную легкость создания программ со скрытыми ошибками, поскольку ненадежные конструкции не проверяются компилятором, как это делается на языке Pascal. Язык С — тонкий инструмент в руках профессионала и удобен для небольших программ, но при разработке на нем больших программных систем группами разработчиков разной квалификации могут возникнуть серьезные проблемы. Мы отметим многие опасные конструкции С и укажем, как не попадать в главные ловушки.
Язык С был стандартизирован в 1989 г. Американским Национальным Институтом Стандартов (ANSI); практически тот же самый стандарт был принят Международной Организацией по Стандартизации (ISO) годом позже. В этой книге делаются ссылки на ANSI С, а не на более ранние версии языка.
C++
В 1980-х годах Бьярн Строуструп, также из Bell Laboratories, использовал С как базис языка C++, добавив поддержку объектно-ориентированного программирования, аналогичную той, которую предоставлял язык Simula. Кроме того, в C++ исправлены многие ошибки языка С, и ему следует отдавать предпочтение даже в небольших программах, где объектно-ориентированные свойства, возможно, и не нужны. C++ — наиболее подходящий язык для обновления систем, написанных на С.
Обратите внимание, что C++ — развивающийся язык, и в вашем справочном руководстве или компиляторе, возможно, отсутствуют последние изменения. Обсуждаемый в этой книге язык соответствует книге Annotated C++ Reference Мanual Эллиса и Строуструпа (издание 1994 г.), которая является основой рассматриваемого в настоящее время стандарта.
Ada
В 1977 г. Министерство Обороны Соединенных Штатов решило провести унификацию языка программирования, в основном, чтобы сэкономить на обучении и стоимости поддержки операционных сред разработки программ для различных военных систем. После оценки существующих языков было принято решение провести конкурс на разработку нового языка, положив в основу хороший существующий язык, такой как Pascal. В конце концов был выбран язык, который назвали Ada, и стандарт был принят в 1983 г. Язык Ada уникален в ряде аспектов:
• Большинство языков (Fortran, С, Pascal) создавались едиными командами разработчиков и были стандартизованы уже после их широкого распространения. Для сохранения совместимости все случайные промахи исходной команды включались в стандарт. Ada же перед стандартизацией подверглась интенсивной проверке и критическому разбору.
• Многие языки первоначально были реализованы на единственном компьютере, и на них сильно повлияли особенности этого компьютера. Язык Ada был разработан для написания переносимых программ.
• Ada расширяет область применения языков программирования, обеспечивая обработку ошибок и параллельное программирование, что традиционно считалось (нестандартными) функциями операционных систем.
Несмотря на техническое совершенство и преимущества ранней стандартизации, язык Ada не достиг большой популярности вне военных и других крупномасштабных проектов (типа коммерческой авиации и железнодорожных перевозок). Язык Ada получил репутацию трудного. Это связано с тем, что он поддерживает многие аспекты программирования (параллелизм, обработку исключительных ситуаций, переносимые числовые данные), которые другие языки (подобные С и Pascal) оставляют операционной системе. На самом деле его нужно просто больше изучать. К тому же первоначально были недоступны хорошие и недорогие среды разработки для сферы образования. Теперь, когда есть бесплатные компиляторы (см. приложение А) и хорошие учебники, Ada все чаще и чаще встречается в учебных курсах даже как «первый» язык.
Ada 95
Ровно через двенадцать лет после принятия в 1983 г. первого стандарта языка Ada был издан новый стандарт. В новой версии, названной Ada 95, исправлены некоторые ошибки первоначальной версии, но главное — это добавление поддержки настоящего объектно-ориентированного программирования, включая наследование, которого не было в Ada 83, так как его считали неэффективным. Кроме того, Ada 95 содержит приложения, в которых описываются стандартные (но необязательные) расширения для систем реального времени, распределенных систем, информационных систем, защищенных систем, а также «числовое» (numerics) приложение.
В этой книге название «Ada» будет использоваться в тех случаях, когда обсуждение не касается особенностей одной из версий: Ada 83 или Ada 95. Заметим, что в литературе Ada 95 упоминалась как Ada 9X, так как во время разработки точная дата стандартизации не была известна
.
- Глава 1
- 1.2. Процедурные языки
- 1.3. Языки, ориентированные на данные
- 1.4. Объектно-ориентированные языки
- 1.5. Непроцедурные языки
- 1.6. Стандартизация
- 1.7. Архитектура компьютера
- 1.8. Вычислимость
- 1.9. Упражнения
- Глава 2
- 2.2. Семантика
- 2.3. Данные
- 2.4. Оператор присваивания
- 2.5. Контроль соответствия типов
- 2.7. Подпрограммы
- 2.8. Модули
- 2.9. Упражнения
- Глава 3
- 3.1. Редактор
- 3.2. Компилятор
- 3.3. Библиотекарь
- 3.4. Компоновщик
- 3.5. Загрузчик
- 3.6. Отладчик
- 3.7. Профилировщик
- 3.8. Средства тестирования
- 3.9. Средства конфигурирования
- 3.10. Интерпретаторы
- 3.11. Упражнения
- Глава 4
- 4.1. Целочисленные типы
- I: Integer; -- Целое со знаком в языке Ada
- 4.2. Типы перечисления
- 4.3. Символьный тип
- 4.4. Булев тип
- 4.5. Подтипы
- 4.6. Производные типы
- 4.7. Выражения
- 4.8. Операторы присваивания
- 4.9. Упражнения
- Глава 5
- 5.1. Записи
- 5.2. Массивы
- 5.3. Массивы и контроль соответствия типов
- Подтипы массивов в языке Ada
- 5.5. Строковый тип
- 5.6. Многомерные массивы
- 5.7. Реализация массивов
- 5.8. Спецификация представления
- 5.9. Упражнения
- Глава 6
- 6.1. Операторы switch и case
- 6.2. Условные операторы
- 6.3. Операторы цикла
- 6.4. Цикл for
- 6.5. «Часовые»
- 6.6. Инварианты
- 6.7. Операторы goto
- 6.8. Упражнения
- Глава 7
- 7.1. Подпрограммы: процедуры и функции
- 7.2. Параметры
- 7.3. Передача параметров подпрограмме
- 7.4. Блочная структура
- 7.5. Рекурсия
- 7.6. Стековая архитектура
- 7.7. Еще о стековой архитектуре
- 7.8. Реализация на процессоре Intel 8086
- 7.9. Упражнения
- Глава 8
- 8.1 . Указательные типы
- 8.2. Структуры данных
- 8.3. Распределение памяти
- 8.4. Алгоритмы распределения динамической памяти
- 8.5. Упражнения
- Глава 9
- 9.1. Представление вещественных чисел
- 9.2. Языковая поддержка вещественных чисел
- 9.3. Три смертных греха
- Вещественные типы в языке Ada
- 9.5. Упражнения
- Глава 10
- 10.1. Преобразование типов
- 10.2. Перегрузка
- 10.3. Родовые (настраиваемые) сегменты
- 10.4. Вариантные записи
- 10.5. Динамическая диспетчеризация
- 10.6. Упражнения
- Глава 11
- 11.1. Требования обработки исключительных ситуаций
- 11.2. Исключения в pl/I
- 11.3. Исключения в Ada
- 11.5. Обработка ошибок в языке Eiffei
- 11.6. Упражнения
- Глава 12
- 12.1. Что такое параллелизм?
- 12.2. Общая память
- 12.3. Проблема взаимных исключений
- 12.4. Мониторы и защищенные переменные
- 12.5. Передача сообщений
- 12.6. Язык параллельного программирования оссаm
- 12.7. Рандеву в языке Ada
- 12.9. Упражнения
- Глава 13
- 13.1. Раздельная компиляция
- 13.2. Почему необходимы модули?
- 13.3. Пакеты в языке Ada
- 13.4. Абстрактные типы данных в языке Ada
- 13.6. Упражнения
- Глава 14
- 14.1. Объектно-ориентированное проектирование
- В каждом объекте должно скрываться одно важное проектное решение.
- 14.3. Наследование
- 14.5. Объектно-ориентированное программирование на языке Ada 95
- Динамический полиморфизм в языке Ada 95 имеет место, когда фактический параметр относится к cw-типу, а формальный параметр относится к конкретному типу.
- 14.6. Упражнения
- Глава 15
- 1. Структурированные классы.
- 15.1. Структурированные классы
- 5.2. Доступ к приватным компонентам
- 15.3. Данные класса
- 15.4. Язык программирования Eiffel
- Если свойство унаследовано от класса предка более чем одним путем, оно используется совместно; в противном случае свойства реплицируются.
- 15.5. Проектные соображения
- 15.6. Методы динамического полиморфизма
- 15.7. Упражнения
- 5Непроцедурные
- Глава 16
- 16.1. Почему именно функциональное программирование?
- 16.2. Функции
- 16.3. Составные типы
- 16.4. Функции более высокого порядка
- 16.5. Ленивые и жадные вычисления
- 16.6. Исключения
- 16.7. Среда
- 16.8. Упражнения
- Глава 17
- 17.2. Унификация
- 17.4. Более сложные понятия логического программирования
- 17.5. Упражнения
- Глава 18
- 18.1. Модель Java
- 18.2. Язык Java
- 18.3. Семантика ссылки
- 18.4. Полиморфные структуры данных
- 18.5. Инкапсуляция
- 18.6. Параллелизм
- 18.7. Библиотеки Java
- 8.8. Упражнения