лекция 5 (Языки программирования (лекции) (2008))
Описание файла
Файл "лекция 5" внутри архива находится в папке "Языки программирования (лекции) (2008)". Документ из архива "Языки программирования (лекции) (2008)", который расположен в категории "". Всё это находится в предмете "языки программирования" из 7 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Онлайн просмотр документа "лекция 5"
Текст из документа "лекция 5"
Языки программирования. Лекция 5.
Атрибуты данных:
1). Имя
Неименованные данные:
-
константы (например просто 1);
-
Объекты из динамической памяти( Т * р= new T объект ,на который ссылается р не именованный );
Все яп, которые мы рассматриваем, характеризуются статическим связыванием имени с данными( Pascal, C++ и т.д. ).
Пример: виртуальные функции
рх->f()
в классе х f() – виртуальная функция , следовательно, связывание динамическое, но связывание с именем происходит статически.
Причина: Посредством введения имени мы вводим всякого рода атрибуты, то статическое связывание позволяет компилятору знать о соответствующих атрибутах в момент трансляции . Т.о. он может лучше контролировать поведение объекта . Если поведение объекта отклоняется, то компилятор может вставлять корректирующий код или выдавать сообщение об ошибке.
Пример яп с динамическим связыванием – Lisp.
2). Тип данных(тд)
тд=мн-во операций+мн-во значений
С точки зрения тд яп бывают:
-
“бестиповые” яп ( скрипт-языки);
Замечание: На самом деле таких языков не бывает( в них типы данных есть, но объект в соответствии со значением , которое ему положено, может принадлежать различным типам, т. е. Тип данных связывается динамически.
-
статически определенные типы (т.е. тип связывается с объектом статически);
-
динамические типы (объектно-ориентированные языки);
Замечание: вводятся статические типы данных и для указателей/ссылок вводятся динамические тд . Указатели/ссылки могут указывать как на статические объекты, так и на динамические.
Пример: яп Си
Класс Т:
Т*х;
Породим от класса Т класс Y. Потом
х=new Y;
Статический тип у объекта, на который указывает х, тип Т, динамический тип не известен , т.к. указатель на Т может указывать на любой производный класс (и только).
Динамический тд относится только к указателям и ссылкам.
3). Адрес
Адресов не имеют:
-регистровые переменные;
-константы;
Пример:
-
Register int x; &x-нельзя!
-
ADD x,2
КОП | Адрес х | 2 |
2-непосредственный операнд.
Мы спускаемся на уровень реализации.
4). Значение
Пример:
В Си# есть обычные константы( в смысле Си ) и readonly – константы, которые могут только считываться после динамического присваивания.
5).Время жизни(вж)
Понятие вж тесно связано с классом памяти, т.к. объекты различных типов реализуются различными классами памяти.
вж | Класс памяти |
Вся программа | Статический класс памяти |
Блок Пример: i и k похожи int i; int main() {int k; } i и k формально различные классы памяти i-в блоке,k-глобальная, но по вж они различаются очень мало, они перестают существовать: k-при выходе из main i-после завершения программы. | Квазистатическая память: -составной оператор; -тело функции/процедуры; Класс чаще всего реализуется системным стеком. Впервые понятие блока, вложенных областей появилось в Algol’е 60. Первые реализации допускали двоякое представление: -нет рекурсии : все объекты внутри блоков статические; -рекурсия: моделировался стек; отличие статических и квазистатических объектов: от обоих можно брать адрес, но
|
По усмотрению программиста | Динамическая память Обязательно должны существовать функции типа: -new( Ада, Pascal, C++ и т.д.)- отводит объект в динамической памяти ; -delete; |
Пример:
В Pascal смешивать статические, динамические и квазистатические объекты нельзя( указатель- только на динамическую память), это сделано из соображений надежности.
В надежных языках:
-
запрещено брать адрес от статических и квазистатических объектов;
-
указатели указывают только на динамическую память;
Но реализация во многом зависит от ОС(PalmОС- реализация языка Си, в котором статические переменные меняют адрес. Все переменные находятся в оп, но есть функция “закрепляющая” переменную в оп).
В современных я зыках других классов памяти и вж нет. Но ведутся переговоры об объектах, которые будут существовать между запусками программы- вечные, persistence( сохраняемые объекты).Но введение подобного класса, требует универсального способа реализации, который очень сложен.
6). Область действия(од)
ОД распространяется на те данные, которые имеют имя. В наших яп имя присваивается как статически, в объявлениях, так и динамически( бестиповые яп):
if(a= =b){v=o;}//JavaScript v –не объявлена ранее
Если a<>b, то v-не появиться.
В традиционных яп:
имя->объект(для этого служит объявление/определение)
од-от начала определения и до конца соответствующей области.
(блоки, классы и т.д.)
ЯП бывают (зависит от характера связывания од) с :
-
статической од( од связывается с какой-то синтаксической конструкцией языка- блок, класс, пакет и т.д.);
-
динамической од( все зависит от цепочки динамической вложенности блоков):
proc P;// псевдо-Pascal
i1: integer;
proc P1;
i2: integer;
P2;
end P1;
proc P2;
i:=0; // в статической од i1:=0;
end P2;
… // в динамической од(-> -вызов)
P1; //P(i1)->P1(i2)->P2 i2:=0;
P2; // P(i1)->P2() i1:=0;
end P;
в статической од: i1:=0;
в динамической од(-> -вызов):
P(среда ссылок: i1)->P1(среда ссылок: i2)->P2(среда ссылок: пусто)
i2:=0;
P(среда ссылок: i1)->P2(среда ссылок: пусто)
i1:=0;
Среда ссылок каждой функции помещается в стек и затем просматривается.
Динамические области ссылок необходимы для гибкости программы, но выполняются эти программы дольше, чем программы со статическими од.
В традиционных яп- статические од. Но в Си++, Delphi, Java есть понятие динамических областей действия- поиск обработчика исключений.(Медицинская страховка дается поликлиникой, но в дороге мы вызываем ближайшую скорую помощь, а не врачей из поликлиники).
Основная часть курса
Часть 1: Традиционные яп
Глава 1: Простые ТД(птд)
(скалярный базис)
Классификация птд:
1). Арифметические(основные)
-целочисленные
-вещественные
->с плавающей точкой
->фиксированные(с фиксированной точкой)(точность измерений, с точки зрения реализации -это числа целые, с физической – вещественные ( термометр, операции с деньгами))
->decimal (В С# 128 битные числа с фиксированной точкой). Нужны для проведения вычислений над очень большими вещественными числами , но с фиксированной точностью. Облегчает перевод данных из внутреннего представления.
(есть в Си#). Он пришел из баз данных, которые ,в свою очередь, от языка Кобол. Остальные типы- производные.
Разделение оправдано из соображений реализации операций.
2). Логические
3). Символьные
4). Порядковые (диапазоны и перечисления)
5). Указатели и ссылки
В паскаль представлены все эти 5 тд.
6). Функциональные(процедурные)- в Turbo Pascal,Модула-2.
Целочисленные тд
Проблемы:
1.представление(количество бит, представление отрицательных чисел
2.универсальность(наиболее полная номенклатура, т.е. наиболее полное представление)
3.надежность(операции не должны приводить к ошибкам)
ЯП бывают:
-фиксирующими представление;
-не фиксирующие представление;
-ADA-фиксирует, но позволяет гибко управлять.
Представление отрицательных чисел не фиксировано в современных яп вообще. Т.к. существуют на рынке архитектуры с представлением, как в обратном коде, так и в дополнительном. Программа должна быть переносима, следовательно, программист не должен зависеть от реализации отрицательных чисел
С:
sizeof(int) в Cи не фиксировано представление.
Т.к. int-родной тип для процессора (размерность int- это размерность процессора)-> эффективность.
В C#,Delphi,Java представление фиксировано-> переносимость.
-
универсальность-> эффективность(желательно иметь наиболее полный набор целочисленных типов)
В Java ориентирован на много платформ и в нем гораздо меньше целочисленных типов данных, чем в Delphi и C#-,которые ориентированы на одну, выбор большой.
-
Причины возникновения ненадежности:
-
переполнение
-
неявное преобразование типов(из-за наличия без знаковых и знаковых чисел)
-
Пример:
Преобразование тд
char c; // ошибка в программе!
while((c=getchar())!=EOF)
{…}
Может зацикливаться. Проблема в преобразовании integer-> char.
-char<integer;
-integer-знаковый, а char-зависит от архитектуры => EOF=-1->255(если без знаковый)-> происходит сравнение с 1.
В Модула-2:
integer->longint- допускается
cardinal(integer без знака)->longint - допускается
integer->cardinal-преобразования нет.
J:integer
I:integer
J:=I; I:=J;- запрещено!
Нельзя смешивать знаковые и без знаковые числа: это может приводить к трудно обнаружимым ошибкам. Официально в Си++(для поддержания С) это не запрещено, если это запретить, то объем работы будет очень велик.
Решение, предложенное Страуструпом: Транслятор с front- транслирует код из Си с классами(Си++) в чистый Си. Потом компилятор компилирует объектный код. Но он был написан на Си++, и в нем было смешение.
Можно вообще отказаться от без знаковых чисел.
Зачем нужны без знаковые числа?
-
Экономия места (16 битная машина:32767 против 65535, если 32 то все ок);
-
Физический смысл- адресная арифметика;
Языкам высокого уровня адресная арифметика уже не нужна.
Оберон:
Byte (без знаковое)->short-> int-> integer-> longint (вложение строгое)
Нет cardinal, т.к. 32 битная архитектура.
Java:
Byte(без знаковое целое) short(знаковое 2-байтное) int(строго 32-байтное) long
C#:
Полная номенклатура
знаковый | б/з |
sbyte | byte |
short | ushort |
int | uint |
long | ulong |
Неявные преобразования:
-В пределах столбца сверху вниз;
-По косой :
byte->short
ushort->int
uint->ulong
Обратные преобразования запрещены. Все остальное должно быть явным.
Синтаксис преобразования:
T-имя типа, l-переменная
(T) l- преобразования в Си, Си++
T (l)- в С++
Переполнение
В С, C++(из соображений эффективности) постулировано, что никакие переполнения к срыву не приводят, т. к. в большинстве архитектур при возникновении переполнения устанавливается флаг:
OF- б/з
CF- знаковые
И большинство архитектур не генерируют прерывание.
В Си# есть управляемые области кода и если происходит переполнение, то возникает исключительная ситуация, если область кода не управляемая, то никакого прерывания не возникает.
Тенденции в современных яп:
-зафиксировать все представления;
-минимизировать ненадежность( запрет неявных преобразований и введение программного контроля);
Наиболее гибкая система целочисленных типов в языке ADA.
6