Языки программирования, 05 лекция (от 19 сентября)
Материал из eSyr's wiki.
Категории: Языки программирования | Лекции | Незавершённые статьи
Предыдущая лекция | Следующая лекция
Содержание |
[править] Связывание
Статическое связывание — во время компиляции
Динамическое связывание — в момент выполнения
- Данный код на С++:
(C++) Х х; Х.F();
- Транслируется в:
(Asm) CALL _F
Когда произойдёт связывание? Кто и в какой момент решает? Правильный из вызова дать нельзя. Для ответа надо посмотреть на объявление Х, и посмотреть, виртуальная функция или нет. Но это может быть недостаточно, так как Х может быть унаследован от ХХ, где функция объявлена виртуальной. Для невиртуальных методов можно по тексту программы можно определить, какая функция вызывается, для виртуальных — в общем случае нет.
[править] Виртуальная машина
Виртуальная машина языка — некая машина, у которой язык программирования является машинным языком. Это понятие возникло в 60-е годы на базе языка Algol 60, так как понятие ВМ позволило разделить окружение языка и сам язык. До Алгол 60 окружение включалось в язык, например, у Паскаля стандартные функции (ввод-вывод) есть часть языка.
Понятие виртуальной машины оказалось не чисто теоретическим понятием. Сейчас понятие ВМ является часто употребляемым и не столь ясным. Идея реализовать в железе ВМ было довольно частой, особенно в 60–70 годы.
- SYMBOL (Европа и Америка), для которой языком был Алгол 60 (не являлась чистой, так как некоторые конструкции языка не были реализованы).
- Burroughs работал на расширенном варианте Алгол 60 со стеком и был чистой ВМ
- в СССР для машин Мир–1, 2, 3 единственным языком был Аналитик — русифицированный и расширенный вариант Алгол 60, например в Аналитике были операции для символьного дифференцирования и интегрирования. Но впоследствии развитие собственных машин было убито и СССР перешло на копирование чужих платформ.</p>
- В 70-е годы получили распространение LISP-ВМ (LISP-machines). Аппаратная реализация была нужна для увеличения быстродействия.
Сейчас количество различных архитектур невелико. И аппаратная реализация выглядит анахронизмом, так как реализация эта дорогая и, что ещё хуже, негибкая, так как языки сложны и отсутствует универсальный язык. Кроме того, в языке имеются недостатки, эти недостатки распространяются на архитектуру. Сейчас же языки ориентируются на архитектуру и базис очень и очень примитивен.
[править] Понятие ВМ в том виде, в котором оно сформировалось
Реализация в виде транслятора в байт-код и оного интерпретатора стандартна для языка Smalltalk. Попытка аппаратной реализации этой ВМ ("Катана") провалилась.
Популярна ВМ для языка Java — JVM (Java Virtual Machine). Sun стандартизовала язык Java, байт-код и набор системных вызовов. Любой интерпретатор байт-кода (например, JRT — Java RunTime) есть конкретное воплощение JVM.
Понятие ВМ оказалось достаточно мощным и гибким. Понятно, за счёт чего обеспечивается гибкость. За счёт того, что мы не зависим от реализации. Например, программы, удовлетворяющие стандарту "Pure Java", действительно переносимы.
Чем мы платим? Производительностью. Например, Lotus Notes, написанная на Java, сильно тормозит. Как только речь идёт о нетривиальных приложениях, сказываются проблемы с производительностью. Спор об эффективности-неэффективности ведётся с 50-х годов.
Каждые 10 лет говорят, что через 10 лет компьютеры будут так быстры, что ничего уже не будет тормозить.
Действительно, сейчас эффективности уделяется меньшее внимание, о чём говорит распространение скриптовых языков — PHP, Perl, JSP, ASP, Python, Ruby. Они используются на стороне сервера, но остаются достаточно специализированными, занимаются обработкой и генерацией текста, и, с точки зрения программирования, это достаточно узкая область, а Java претендовала на роль универсального языка, и роль эффективности тут больше.
.NET Framework — ещё одна попытка, где стандартизируется только окружение, а не байт-код. ЯП .NET — MIL — компилируется just-in-time (JIT). Это несколько более эффективно. То есть, стандартизован некий виртуальный язык. Одно время говорили, что вместо WinAPI будут использовать защищённые вызовы .NET, но это нескоро, так как как только начинаешь писать что-то хитрое, сразу надо вспоминать, как вызывать WinAPI.
[править] Часть 1. Основные понятия традиционных процедурных ЯП
Будем рассматривать не Алгол и Фортран, а современные ООП языки, точнее ту часть, где они наследуют традиционную парадигму
- Базис
- скалярный
- структурный
- Средства развития
- Средства защиты
[править] Глава 1. Скалярный базис.
[править] Пункт 1. Классификация простых типов данных
Простые типы данных (они же примитивные) — не имеют внутр структуры.
- Арифметические типы
- Целые
- Вещественные
- С плавающей точкой
- С фиксированной точкой — не во всех языка поддерживается это разделение
- Логический тип
- Символьные типы
Целые, символьные и логические ТД сводятся к целым.
Типы, основанные на других типах:
- Ссылочные типы / Указатели
- Порядковые типы
- Перечисление
- Диапазон — производный тип данных, опирающийся на другой тип данных — перечислимый
- Процедурные (функциональные) типы данных — не есть указатель, но его разновидность — в Modula-2, Oberon, Ada 95.
Любой ЯП обладает подобным набором ТД. Традиционно базысным типом является целый тип. Инновационный подход - использование строк как базисного типа.
[править] Пункт 2. Целые типы и проблема представления беззнаковых чисел
Две проблемы, возникающие при реализации целых чисел: Представление беззнаковых чисел и длина
Решения проблемы знаковых-беззнаковых типов:
-
Pascal — два отдельных типа
-
C — две разновидности типа
-
Java — только знаковый
в C# — все типы парами: short — ushort; int — uint; long — ulong. По традиции byte беззнаковый, посему sbyte — byte. Длина зафиксирована: byte – 1, short – 2, int – 4, long – 8 байт.
Какая проблема связана с беззнаковым типом — проблема преобразований из и в знаковый тип.
- Классический пример (На одной архитектуре он зацикливается, на другой работает нормально):
(C) char c; while ((c=getchar())!=EOF) {}
Проблема в том, что EOF = –1. И все функции стандартной библ возвращают знаковый тип — int. В одних архитектурах char знаковый, в других — беззнаковый. Тогда получаем такую цепочку преобразований:
0xFFFF => 0xFF => 0x00FF.
Для правильной реализации надо писать int c.
В стандартном Паскале не было беззнаковых типов.
В Modula-2 было два типа INTEGER и CARDINAL, которые неявно друг к другу не преобразовывались.
Программист-профессионал должен включать макс уровень предупреждений и добиваться, чтобы у него предупреждений не было.
Была мода в 80-е годы делать знаковый и беззнаковый типы несовместимыми, так как явное преобразование заставляет задумываться над ошибками. Страуструп в первом варианте Си с классами запретил преобразование между знаковыми и беззнаковыми типами. Ни одна из существ программ на языке C не прошла тест на компиляцию в первом варианте C++. Но эти программы работают, правильно работают. Объяснение состоит в том, что профессионалы представляют проблемы, с этим связанные, и эти проблемы решают. В результате неявные преобразования были разрешены (так как главным критерием при проектировании С++ являлась совместимость со стандартными библиотеками), но при опасных выдаётся предупреждения. Дабы не ограничивать возможности программиста, Страуструп в результате сдался.
Другим решением была в Java, самое простое решение — запретили беззнаковые типы данных. А зачем вообще нужны беззнаковые типы? Чуть больше диапазон значений в одну сторону, что было важно раньше, когда машины были большие, а байты маленькие. И беззнаковые типы тогда были нужны.
В Pascal не было беззнаковых типов — В Modula-2 были два несовместимых типа — В Обероне один беззнаковый тип байт и остальные только знаковые.
Modula создавалась для 16 битных архитектур, и это было важно, а Oberon для 32, где неважно, 2 миллиарда или 4.
Почему же в Delphi и C шарп есть беззнаковые типы? Для адресов и манипуляции с ними. Поэтому в языках системного программирования оставляют беззнаковые типы, а Java не является языком для системного программирования, посему проблем с беззнаковостью решили не иметь.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
Календарь
чт | вт | чт | вт | чт | вт | чт | вт | чт | вт | |
Сентябрь
| 05 | 07 | 12 | 14 | 19 | 21 | 26 | 28 | ||
Октябрь
| 03 | 05 | 10 | 12 | 17 | 19 | 24 | 26 | 31 | |
Ноябрь
| 02 | 14 | 16 | 21 | 23 | 28 | 30 | |||
Декабрь
| 05 | 07 | 12 | 14 |
Материалы к экзамену
Сравнение языков программирования