лекции (2004) (1160823), страница 4
Текст из файла (страница 4)
Виды стандартов:
1.С точки зрения принимающего органа :
-
международные стандарты (ISO)(за каждый яп выбирается ответственная национальная группа);
-
национальные (Pascal - британский BSI, C - ANSI);
-
неправительственные (IEEE - профессиональное сообщество инженеров по электронике, IEEE-754 - стандарт на плавующую арифметику. ECMA - европейский союз производителей компьютеров, стандарт ECMA Script - ни что иное, как JavaScript).
Преимущество C#:
Фирма Sun категорически отказывается от стандартизации языка Java.
C# - стандарт ECMA.
2. Открытые и закрытые стандарты.
Открытые стандарты определяют функционирование только правильных программ. Они не специфицируют поведение всех программ. Они описывают поведение только некоторых программ на соответствующем ЯП.
Пример:
f(i++, a[i]) - правильная с точки зрения описания Си функция содержит побочный эффект. Но результат исполнения зависит от конкретной реализации(зависит от порядка вычисления выражений ). Открытые стандарты не описывают поведение при неправильной программе.
Закрытые стандарты полностью определяют поведение, в том числе и выдачу ошибок.
Из рассматриваемых языков закрытый стандарт имеет язык Ада.
Открытый стандарт неизбежно появляется при попытке объединить несколько различных реализаций ЯП.(Fortran, C++). Все стандарты не разрабатываются как открытые, т.к. сложно предугадать что же будет наилучшим.
3. Опережающие и по факту.
Опережающие- сначала стандарт, потом язык.
Самые успешные стандарты ЯП - по факту.
И почти все по факту - открытые стандарты.(Но стандарт Паскаля является закрытым)
Самый яркий пример опережающего стандарта - стандарт языка Ада.
Понятие атрибутов данных
Для всех данных являются наиболее важные следующие 6 основных атрибутов:
1. Имя;
2. Тип;
3. Значения;
4. Адрес (местоположение);
5. Время жизни;
6. Область действия.
Они в принципе не меняются при переходе от одного яп к другому.
Языки программирования. Лекция 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 |
Неявные преобразования: