
- •2 Сравнительный анализ языков программирования высокого уровня Си и Паскаль
- •2.1 Структура программы
- •2.2.2 Пользовательские типы
- •2.3 Арифметические операции
- •Окончание таблицы 2.3.1
- •Окончание таблицы 2.3.2
- •2.4 Указатели и векторные типы данных
- •2.5.2 Операторы-переключатели
- •2.6.2 Безусловный переход
- •2.7 Пользовательские подпрограммы
- •2.8 Итоги анализа сравнения языков программирования Паскаль и Си
- •3.2 Реализация задания
- •3.3 Алгоритмы, реализованные в процессе решения задачи
Окончание таблицы 2.3.2
Оператор |
Название |
Класс |
Приоритет |
Ассоциативность |
<< >> |
Сдвиг влево и вправо |
Бинарный |
11 |
Слева направо |
< > <= >= |
Отношения |
Бинарный |
10 |
Слева направо |
== != |
Равенство / неравенство |
Бинарный |
9 |
Слева направо |
& |
Побитовое И |
Бинарный |
8 |
Слева направо |
^ |
Побитовое исключающее ИЛИ |
Бинарный |
7 |
Слева направо |
| |
Побитовое ИЛИ |
Бинарный |
6 |
Слева направо |
&& |
Логическое И |
Бинарный |
5 |
Слева направо |
|| |
Логическое ИЛИ |
Бинарный |
4 |
Слева направо |
? ; |
Условие |
Тернарный |
3 |
Справа налево |
= += -= *= /= %= <<= >>= &= ^= |= |
Присваивание |
Бинарный |
2 |
Справа налево |
Оператор |
Название |
Класс |
Приоритет |
Ассоциативность |
, |
Последовательная оценка |
Бинарный |
1 |
Слева направо |
Приведение типов в Си происходит автоматически в тех местах, где это возможно без потенциальных потерь. Так, к примеру, приведение типа char к типу float компилятор проведет сам, а обратное преобразование придется делать явно. Также в Си в сравнении с Паскалем появляется адресная арифметика – арифметические операции допустимы для указателей, и во многих случаях происходит неявное преобразование между целочисленными типами и указателями. Однако эти преобразования срабатывают не всегда. К примеру, при присваивании указателю целочисленной константы с целью установить его в данный адрес компилятор сообщит о несоответствии типов. В таких случаях также необходимо явное приведение.
2.4 Указатели и векторные типы данных
В рассмотрении типов и операций необходимо отдельно выделить векторные типы данных и указатели. В предыдущем разделе было указано на наличие адресной арифметики в языке Си; необходимо указать, к каким выгодам это привело при работе с векторными типами данных.
Под векторным типом данных понимается организация типа по принципу структуры, в которой все элементы одного и того же типа. Это массивы и строки. Под строки в языке Паскаль выделен специальный тип, о котором говорилось выше. Массивы в языке Паскаль существуют как одномерные, так и многомерные. Для обозначения компонент массива используется имя переменной-массива и так называемые индексы, которые обычно указывают желаемый элемент. Тип индекса может быть только порядковым (кроме LONGINT). Чаще всего используется интервальный тип (диапазон). Описание типа массива задается следующим образом: TYPE имя_типа = ARRAY[список индексов] OF тип. Здесь имя типа - допустимый идентификатор; список индексов - список одного или нескольких индексных типов, разделенных запятыми; тип - любой тип данных. Вводить и выводить массивы можно только поэлементно, над массивами не определены операции отношения. Сравнивать два массива также можно только поэлементно. Глубина вложенности многомерных массивов произвольная, поэтому количество элементов в списке индексных типов (размерность массива) не ограничена, однако не может быть более 65520 байт [11].
Массивы в Си в общих чертах имеют те же свойства, что и массивы в Паскале. Так, многомерность их также не ограничена, операции допустимы лишь посимвольно. Но главное отличие заключается в том, что имя массива есть указатель на первый его элемент, причем с этим указателем можно работать как с отдельной переменной. Нельзя изменять значение этого указателя, но возможно разыменовывать его и получать его адрес. Перемещение по элементам массива может проходить как через индексирование, так и через смещение относительно адреса, лежащего в переменной имени массива. Так как указатель никак кроме значения не связан с массивом, то допустимо пересекать границы массива в обе стороны. С одной стороны это дает большую гибкость и больше возможностей, с другой – это потенциальный источник ошибок.
Вернемся непосредственно к указателям. Так как указатель содержит адрес объекта, это дает возможность «косвенного» доступа к этому объекту через указатель. Унарная операция «&» в Си выдает адрес объекта; эта операция применима только к переменным и элементам массива, конструкции с использованием численных и строковых констант являются незаконными. Нельзя также получить адрес регистровой переменной. Унарная операция «*» рассматривает свой операнд как адрес конечной цели и обращается по этому адресу, чтобы извлечь содержимое [4]. Тип указателя неразрывно связан с информацией, хранимой по содержащемуся в нем адресу. Несколько указателей разных типов могут содержать один и тот же адрес, но при этом информация, которую они вернут при разыменовании, будет различаться. Исходя из этого, возникает следующая особенность адресной арифметики в Си: при увеличении указателя на n смещение в байтах будет равно произведению размера типа разыменованного указателя на n. Таким образом, любой указатель рассматривает всю память как массив элементов своего типа, и перемещается по памяти поэлементно. В Паскале адресная арифметика отсутствует; набор допустимых действий с указателями это разыменовывание и получение адреса. Эти действия были рассмотрены в разделе 2.3.
2.5 Операторы ветвления
Оператор ветвления [12] - оператор, конструкция языка программирования, обеспечивающая выполнение определённой команды (набора команд) только при условии истинности некоторого логического выражения, либо выполнение одной из нескольких команд (наборов команд) в зависимости от значения некоторого выражения.
2.5.1 Условные операторы с несколькими условиями
В языке Паскаль имеет место синтаксис, согласно которому в ветвях условного оператора может быть помещена только одна команда. Поэтому для размещения там большего количества команд они группируются в составной оператор с помощью пары ключевых слов BEGIN и END. Ветвь ELSE необязательна. Ключевые слова BEGIN и END необходимы, только если операторов несколько (например, из соображений единообразия оформления кода) [12]. Оформление условного перехода IF … THEN … ELSE выглядит следующим образом: на первое место выносится ключевое слово IF, после которого следует через пробел выражение или переменная, возвращающие логический тип. В случае, если выражение составное, используются круглые скобки. Выражение закрывается ключевым словом THEN, после которого записывается оператор, выполняющийся в случае истинности условия. В случае, если необходимо обработать и случай ложности высказывания, используется ключевое слово ELSE. Перед ELSE недопустим знак завершения оператора «;». При необходимости после ELSE допускается начинать новый оператор IF, который будет рассматриваться в общей совокупности с первым IF.
В языке Си условный оператор структурно аналогичен оператору в Паскале. Отличие состоит в том, что условие должно быть записано в круглых скобках, исчезает ключевое слово THEN, а вместо ключевых слов BEGIN и END используются фигурные скобки «{}» [12]. Условные операторы Си проигрывают условным операторам Паскаля в случае определения диапазонов и принадлежности к множествам, так как оператор принадлежности к множеству IN (раздел 2.3, операции Паскаля) работает быстрее двух операторов сравнения с верхней и нижней границей множества [5].