Языки программирования, 07 лекция (от 26 сентября)
Материал из eSyr's wiki.
Предыдущая лекция | Следующая лекция
Содержание |
Часть 1. Основные понятия традиционных процедурных ЯП
Глава 1. Скалярный базис.
Пункт 5. Символьные типы данных
В любой программе фигурирует 2 алфавита:
- символы для ввода/вывода (char)
- символы для записи самой программы (триграфы)
Начало стандартизации
Вначале был хаос, но уже в 1970-х был создан 7-битовый стандарт ASCII-7, в котором и писались сами программы. С тех пор проблемы остались только с 1 символьным типом.
(Pascal) a^ - так в ASCII-7 записовалось адресное выражение Pascal
Тогда же - ANSI ISO 10646 на отображение символьного типа данных.
Языки бывают двух видов:
- символьный ТД совместим с целочисленным
(C) c++; c+=1;
- символьный ТД не совместим с целочисленным
(Pascal) c=chr(ord(c)+1); c=succ(c);
Еще один стандарт тех времен - ISO 8809 "Latin 1". Он позволял преобразовыть текс на языках с расширенной латиницей в тект на латинице. Но таких языков было мало, да и кириллические языки никак не учитывались. Результат - в большинстве стран свои раскладки, где 0-127 из ASCII-7, 128-255 специфично для страны.
(Флуд от ZOK'a) А в России одну такую раскладку придумать не смогли. Результат - полный хаос кодировок, с которыми приходится мириться для обратной совместимости и по сей день.
Дальнейшие развитие
1980-е ознаменовались огромным экономическим подъемом Японии. Тогда-то и встал острый вопрос о кодировании их языка. Родилась новая концепция.
CS (Character Set) - Таблица соответствий названий символов (не изображений!) и их кодов.
- SBCS (Single Byte CS) - устарела, ее не хватает даже для Европы
- MBCS (Multi Byte CS) - для Японии, переменная байтовая длина
- DBCS (Double Byte CS) - 2 или 4 байта
- UCS-2, она же UNICODE
- UCS-4
Сейчас UNICODE поддерживается на уровне операционных систем. Это вызывает сложности с поддержкой устаревших программ, обращающихся к прежним системным вызовам. Для них строки перекодируются на лету.
Также UNICODE реализован в родных типах данных новых языков программирования C# и Java, разработанных в 1990-х с нуля.
Сейчас в обществе остро стоит проблема интернационализации (жаргон - i18n). ПО, написанное для одной страны должно быть пригодным к использованию в других странах. Для этого есть 2 пути
- локализация (фактически, переписывание отдельных частей кода для конкретной страны)
- глобализация (учитывание интернациональных факторов сразу)
Факторов много. В .NET и Java даже введено специальное понятие culture, включающее в себя язык, формат представления дат и многое другое.
Как это было в Ada
В Ada это было криво, но интересно. Существовал базовый набор CHARACTER, но можно было создавать и свои символьные типы, просто перечисляя значения.
(Ada) Type MyChar is (' ', '0', '1', ... , '9', 'A', ...);
Трасформационные форматы
UNICODE всем хорош, но как правило пересылая по сети символы ASCII-7, мы очень много теряем в производительности. Для борьбы с этим был разработан UTF (UCS Transformation Format).
UTF-7 представяет Unicode через серию 0-127.
UTF-8
- значения 0-127 (7 значащих бит)
- преобразуется в 1 байт
- [0][7 бит]
- значения 128-2047 (11 значащих бит)
- преобразуется в 2 байта
- [110][5 бит] [10][6 бит]
- значения 2048-65535 (16 значащих бит)
- преобразуется в 3 байта
- [1110][4 бит] [10][6 бит] [10][6 бит]
Также существует UTF-16 для представления UCS.
Все это - вопрос окружения, а не языка. Отличный пример этому - взаимодействие Motif—Xt—Xlib. Cтрока создается, пересылается, обрабатывается, не задумываясь о Transformation Format.
(C) XmCreateString("String", ...);
Пункт 6. Порядковые (ограниченные) типы данных
Порядковые типы данных (также называются ограниченными) бывают двух видов:
- перечислимые типы (будут рассмотрены в этой лекции)
- диапозоны (будут рассмотрены в следующей лекции)
Перечислимые типы
Множество абстрактных именованных значений, упорядоченных слева направо.
(Pascal) type DOW = (Monday, Tuesday, …);
(Ada) type Color is (Red,Green, …);
Операции:
- Переход к предыдущему/следующему элементу
(Pascal) v = pred(v); v = suxx(v);
- Преобразование в целый тип и обратно
(Modula-2) T v; i = ord(v); v = val(T,i);
В Ada реализовано как статическое, так и квазистатическое преобразование.
Перечеслимые типы появились впервые вроде бы в Pascal. После этого так или иначе реализовано почти во всех языках. В том числе и в C.
(C) enum DOW {MONDAY, TUESDAY, …};
Это почти то же самое, что и:
(C) #define DOW int #define MONDAY 0 #define TUESDAY 1 …
При этом разрешены неявные преобразования (будет warning)
(C) DOW d; int i; d = i; i = d;
И даже так:
(C) d = -1;
Вот это уже возмутительно и для программирования не пригодно. Потому и не принято пользовать. Впрочем C за это ругать не стоит. Зачем ассемблеру ограничивать программиста? Впрочем, в C++ этот опыт учли:
- Перегрузка имен работает
(C++) void f(); void f(T1); void f(T2); void f(int);
- Неявное преобразование из int запретили
(C++) i = e; e = (T)i;
- Плюс была внедрена очень полезная вещь:
(C++) enum Color { RED = 0xFF0000; GREEN = 0x00FF00; BLUE = 0x0000FF; … }
Поэтому в C++ перечислимый тип пользуют куда чаще, чем в C.
Впрочем, не везде все так радужно.
- В Modula-2 возможен конфликт имен, т.к. при импортировании типа мы импортируем еще и константы.
(Modula-2) FROM M IMPORT T;
- Oberon — язык системного программирования, там баги и конфликты не нужны. Потому там от перечислимого типа отказались.
- В Ada эти конфликты просто разрешили, что тоже до добра не доводит.
Помимо конфликта имен есть еще один сурьезный минус: перечислимый тип наследуется, но не расширяется, что не соответствует концепции ООП.
(С++) class X { enum T { … }; virtual T f(); }
Поэтому в Java перечислимого типа нет. Но в C# от него не отказались. Более того, придумали замечательную аргументацию, зачем же он нужен. В современном программировании язык и среда разработки бывают тесно связаны. Компонентный подход, при котором на формочку размещают кнопочки, выбирают в меню их свойства и автоматически генерят большую часть кода, весьма популярен.
(параметры среды разработки) OpenMode OM_READ OM_WRITE OM_RW
В 1980-х наметилась тенденция разделения реализации и определения.
(Eiffel) class X { void f(); } void x::f(){ … }
В соответствиии с этими условиями в C# найдено решение проблемы конфликта имен.
(C#) enum C {C1,C2,C3}; C x; x=C.C1; /* по-другому никак */
(C#) [flags] enum Mode { R=1, W=2, RW=R or W }
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 |
Материалы к экзамену
Сравнение языков программирования