Лекция 10 (лекции (2002))

2019-09-19СтудИзба

Описание файла

Файл "Лекция 10" внутри архива находится в папке "лекции (2002)". Документ из архива "лекции (2002)", который расположен в категории "". Всё это находится в предмете "языки программирования" из 7 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .

Онлайн просмотр документа "Лекция 10"

Текст из документа "Лекция 10"

Лекция 10

По настоящему переменный набор параметров поддерживают только C/C++ и С#.

Пример:

printf(const char *,…);

В этих языках есть специальные макросы для работы с переменным числом параметров:


va_list

va_end

va_start

Общая идея: все параметры, которые загружаются в переменную list совместимы с целочисленными ТД или с указателями, а интерпретация остаётся на совести программиста, например, в printf(); параметры выбираются из стека в зависимости от информации, которая находится в процедуре в строке.

Это решение сразу стало критиковаться в связи с ненадёжностью, так как в этом случае ни компилятор, ни кто-то ещё не в состоянии произвести ни динамический, ни статический контроль. Зачем такая конструкция была введена (В С++ понятно из-за концепции совместимости)? Её наличием легко была решена проблема, связанная с вводом-выводом.

Даже в языках, не поддерживающих переменный список параметров, есть процедуры, которые реально поддерживают переменный список. Например, стандартный Паскаль: write(…); - это как бы псевдопроцедура (процедура, которую нельзя написать на самом языке), про которую компилятор знает достаточно много, отсюда у неё и получается переменный список параметров. Здесь же два подхода: вопрос удобства программирования (вывод разнородной информации) или языковая концептуальная целостность, упрощения языка и повышения надёжности. Такой подход принят в семействе языков, опирающихся на язык Паскаль: Модула 2, Оберон и так далее – нет процедур с переменным числом параметров. Надо вывести конструкцию вида: строка-int-строка. Оберон:

IMPORT InOut;

Это стандартный библиотечный модуль, содержащий все процедуры ввода-вывода.

InOut.WriteString(“count = “);

InOut.WriteInt(cnt);

InOut.WriteCh(‘.’);

InOut.WriteLn;

А на Си: printf(“count = %d.\n”, cnt); и если мы забудем указать переменную cnt, то формально ошибки не будет, но будет напечатано какое-то число из стека (оно будет проинтерпретировано как целое число, загружающая программа загружает параметры в стек и их выгружает и, формально, никакого слома программы не произойдёт), чего при описанной выше системе ввода-вывода в принципе не может быть (мы либо просто забываем cnt, либо никаких ошибок быть не может). Но с другой стороны здесь язык становится несколько проще, и программировать становится удобней.

В С++ у нас есть класс CString, и его метод S.Format(“…”,…); реализует sprintf();. Многие программисты продолжают придерживаться этого подхода, следовательно, остаётся ненадёжность.

Один из подходов – статически параметризуемые ТД. Мы уже говорили о статическом перекрытии операций. Это некоторые процедуры с одинаковыми именами, но разным типом и числом (ограниченным, т.е. псевдобесконечного списка параметров написать нельзя) параметров. В Аде таким образом реализована процедура PUT( ,…).

В С++ богатый набора встроенных операций, которые можно переопределять (в том числе и стандартные знаки операций).

Надёжная библиотека ввода-вывода:

iostream.h

(“<<”, “>>” операции сдвига вправо, влево)


<< e - вывод объекта в канал

ch >> obj - операция ввода из канала

Есть ТД iostream (поток ввода-вывода). Каждая операция возвращает:

iostream& operator << (iostream& int, T x);

iostream& operator >> (iostream& int, T x);

И для каждого ТД, для которого хотим определить ввод-вывод, переопределяем эти операции (как правило, на базе введённых в iostream ТД). А возвращаемое значение – это ссылка на первый аргумент. Выполняется слево-направо. Получается мощная и красивая схема:

cout << “count = “ << cnt << ‘.’ <<endl;

Надёжно и читабельно. Также существуют объекты специального типа, которые служат модификаторами ввода-вывода, они позволяют управлять форматом, например, endl, модификаторы, позволяющие изменять ширину поля и т.д.. Вся мощь библиотеки stdio.h сохранена и никаких проблем с надёжностью нет. Но это достигнуто за счёт переопределения стандартных знаков операций, и это наглядно. Но язык усложняется, за счёт введения достаточно нетривиальных вещей.

Альтернативный подход: концепция динамической идентификации типов в C#. Наблюдение за процедурами с переменным числом параметров показывает, что есть некий список параметров, который мы можем проинициализировать. А макросы va_start, va_end позволяют нам итерировать по этому списку. Проблема Си/С++ в том, что мы не знаем, что же на самом деле подставляется в эти параметры и из-за этого соответствующая ненадёжность.

Если у нас язык таков, что Object – базовый ТД, из которого происходят элементы всех классов (все объекты), к нему можно свести любой тип, с помощью механизма обёрток (boxing). В Delphi - это TObject, в Java – Object, а в C# - object. К тому же в этих ЯП поддерживается динамическая идентификация типа (проверка является ли этот объект объектом данного типа, иначе генерируется исключение).

ТД ParamArray – представляет переменный список параметров в качестве массива, каждый из элементов которого - объект, типа Object, который на самом деле есть ссылка на объект класса или обёртка (псевдообъект) структуры или простого значения. У обрабатывающей процедуры последний параметр ParamArray и она работает с ним как с массивом, и вывод осуществляется в зависимости от того, что за элементы в нём. Тут нет никакого статического контроля, но есть динамический. Но кто упрятывает параметры в обёртки. Если мы делаем это сами, то это можно реализовать на любом ЯП самим описав ТД ParamArray и т.д.. Это неудобно и мы теряем все преимущества переменного списка параметров. Очевидно, что это должен делать не программист. В C# это встроенный ТД (ParamArray).

Общее правило - компилятор ищет точное соответствие:

void f(T1 x);

void f(T1 x, T2 x);

void f(T1 x, ParamArray objc);

T1 a, T2 b, T1 c, T3 d

f(a);

f(a, b);

f(a, d);

Пусть T1, T2 и T3 никак не связаны (С наследованием чуть сложнее). Следовательно, точное соответствие не было найдено и он выбирает третий вариант функции, автоматически формируя массив из одного элемента.

f(c, a, b, d);

В данном случае формируется массив из трёх элементов. Таким образом построена библиотека ввода-вывода (Паскаль: WriteLn(форматная строка, ParamArray);), с контролем типов объектов.

В Java более простые правила. Ввод-вывод строк: у каждого объекта (он происходит от ТД Object) есть метод toString, который и применяется по необходимости (компилятор смотрит на контекст):

String s;

int i;

s+i;

Где ”+” – операция конкатенации для строк. i завертывается в оболочку класса Int (который происходит от ТД Object), вызывается метод toString и к строке s добавляется символьное представление i. Следовательно, получаем одну процедуру вывода: вывод строки, а её аргумент – это совокупность объектов, для которых вызывается метод toString. Для нового класса переопределяем метод toString. Похоже на прошлый подход.

ParamArray и прочее в C# появилось, чтобы программисты с С++ легче переходили на С#, а во-вторых в некоторых случаях (например, когда мы пишем процедуры обработчики событий) у нас приходит переменный список параметров и априори мы не можем предсказать какой он будет. Но оно надёжно за счёт динамической идентификации типов. В С++ это тоже есть, но там нет того, что каждый объект происходит от общего и поэтому там ограниченные возможности подобного рода решений.

Глава 5

Определение новых ТД

П.1. Концепция уникальности ТД (Основные проблемы)

Более точная формулировка понятий, строгая и сильная типизация. Их постоянно мешают и непонятно, то ли Си со строгой, то ли с сильной типизацией. Мы определим концепцию уникальности типов, и язык имеет тем боле сильную или строгую типизацию, чем он ближе к этой концепции. Лучше всех удовлетворяет язык Ада. 4 пункта:

1)Каждый объект данных имеет ТД, и этот тип единственен и статически определим.

Типы данных это как бы классы эквивалентности, на которые разбиваются все объекты. То есть не может быть ни константы, ни переменной без ТД. Говоря «статически определим» имеем в виду, что, глядя на текст программы, мы всегда можем определить к какому ТД он принадлежит (Паскаль: по виду константы определяли её тип), иначе – сообщение об ошибке. В Аде у нас есть уточнитель типа данных (например, когда константа принадлежит к нескольким перечислимым ТД): T’e и компилятор всегда знает всё о ТД. Такая концепция во всех традиционных ЯП, и именно из-за этого они с одной стороны являются достаточно эффективными (компилятор может оптимизировать). Но недостатком такого подхода является то, что все ТД разбиваются на непересекающиеся классы, и теряется гибкость.

2)Типы эквивалентны тогда и только тогда, когда их имена совпадают.

Это именная эквивалентность типов, все традиционные современные ЯП поддерживают её (с небольшими отклонениями). Существует ещё и структурная эквивалентность (в первых ЯП, когда типизации уделяли мало внимания речь шла именно о ней – PL|I): ТД совпадают, если их структуры совпадают. От структурной эквивалентности отказались (так как при нём тип – это набор значений), сейчас главное в типе – набор операций (даже на основе одной и той же структуры). Так же, если мы рассмотрим сложные ЯП, структурная эквивалентность двух рекурсивных типов может быть алгоритмически неразрешима. Но иногда отступают от именной эквивалентности: в большинстве старых ЯП есть синонимия типов, например, в Паскале:

Type T = integer;

Типы T и integer теперь синонимы. Данные одного типа могут появляться везде, где появляются данные другого типа и наоборот. В Си и C++ то же (typedef). Здесь типы эквивалентны, если имена совпадают, либо они синонимичны. Это было введено из соображений лучшей документируемости. С точки зрения надёжности, такая конструкция даёт мало. Например, пусть у нас есть три типа данный, синонима integer: Length, Width, Square. Но мы можем к площади прибавить ширину или длине присвоить отрицательное значение.

В Аде (производные типы, введём с помощью специальной концепции нового ТД, который наследует всё множество значений и всё множество операций, эти величины):

type Length is new Integer;

Width is new Integer;

Square is new Integer;

Это совершенно разные типы и их нельзя смешивать.

3)Каждый ТД имеет свой набор операций с фиксированным набором параметров.

Имеется в виду, что фиксированы их число и типы. Переменный список параметров – отклонение от этой концепции.

4)Неэквивалентные ТД несовместимы по операциям.

Тип данных int имеет один набор операций (+, -, *). В Аде у типов Length, Width и Square одни и те же операции, но так как они не эквивалентны из-за разных имён, то их смешивать нельзя. Но мы можем переопределить операцию *:

Length*Width=Square

И как следствие, получить более надёжную программу. Если грамотно определить систему типов, то многие ошибки будут найдены ещё на стадии компиляции.

ЯП, полностью поддерживающий 1)-4) – надёжный. Эта концепция по языку Ада, а другие ЯП ослабляют свойства этой типизации и менее надёжны. В Аде нет синонимии типов, но мы можем переопределять операции, также полностью запрещено неявное (вставляемое компилятором) приведение типов (нарушение 4)):

v:=e

Типы v и e должны совпадать. А компилятор может вставлять или не вставлять контроль. Но между подтипами неявное преобразование возможно, но оно может сопровождаться контролем:

A: Tarr(1..10);

B: Tarr(2..11);

A := B;

Присвоение корректно, так как совпадают динамические атрибуты A’Length и B’Length. Если компилятор не может определить их длины (А и В – формальные параметры) он там вставляет проверку на динамический атрибут «длина». В других ЯП неявные преобразования, которые ухудшают надёжность.

Свежие статьи
Популярно сейчас
Как Вы думаете, сколько людей до Вас делали точно такое же задание? 99% студентов выполняют точно такие же задания, как и их предшественники год назад. Найдите нужный учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
5224
Авторов
на СтудИзбе
426
Средний доход
с одного платного файла
Обучение Подробнее