ebook img

C++ 14: устройство и применение PDF

355 Pages·1.584 MB·Russian
Save to my drive
Quick download
Download
Most books are stored in the elastic cloud where traffic is expensive. For this reason, we have a limit on daily download.

Preview C++ 14: устройство и применение

С++14: устройство и применение (рабочая версия) Лебедев П.А. 13 января 2016 г. ОГЛАВЛЕНИЕ Оглавление Предисловие v I Общие сведения о языках программирования 1 1 Введение в языки программирования 2 1.1 Определение языка программирования и его аспектов . . . . . . . . . . . . . . . 3 1.2 История языков программирования . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.3 Парадигмы программирования . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 1.4 Инструментальные средства . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 1.4.1 Трансляторы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 1.4.2 Другие инструментальные средства . . . . . . . . . . . . . . . . . . . . . 9 2 Основные понятия архитектуры ЭВМ 11 II Язык программирования C++ 14 3 Обзор и основные понятия языка C++ 15 3.1 Стандарт ISO/IEC 14882:2014(E) . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 3.2 Обзор процесса трансляции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 3.3 Лексический состав языка . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 3.4 Типизация . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 3.5 Обзор структуры программы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 3.6 Пример первой программы. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 4 От теории к первой программе 26 4.1 Основные арифметические типы данных . . . . . . . . . . . . . . . . . . . . . . 26 4.1.1 Стандартные целые типы данных. . . . . . . . . . . . . . . . . . . . . . . 26 4.1.2 Стандартные типы с плавающей точкой . . . . . . . . . . . . . . . . . . . 32 4.1.3 Стандартные преобразования арифметических типов . . . . . . . . . . . 34 4.1.4 Операция приведения типов static_cast . . . . . . . . . . . . . . . . . . . 35 4.2 Основные выражения с арифметическими операндами . . . . . . . . . . . . . . 35 4.2.1 Арифметические операции . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 4.2.2 Операции с логическими значениями. . . . . . . . . . . . . . . . . . . . . 37 4.2.3 Порядок вычисления операций в выражениях . . . . . . . . . . . . . . . 38 4.3 Объекты и доступ к ним . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 4.3.1 Простые определения объектов . . . . . . . . . . . . . . . . . . . . . . . . 40 4.3.2 Категории значений. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 4.3.3 Чтение и запись объектов. Операция простого присваивания. Оператор- выражение. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 4.3.4 Операции составного присваивания, инкремента и декремента . . . . . . 44 4.3.5 Пример компиляции выражения . . . . . . . . . . . . . . . . . . . . . . . 46 4.4 Введение в функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 4.4.1 Определения функций . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 4.4.2 Операция вызова функции . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 4.5 Введение в форматированный ввод/вывод . . . . . . . . . . . . . . . . . . . . . . 52 4.5.1 Форматированный вывод. . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 4.5.2 Форматированный ввод . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 4.6 Использование среды Qt Creator . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 i ОГЛАВЛЕНИЕ 4.6.1 Настройка компилятора . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 5 Структурное программирование на языке C++ 59 5.1 Использование функций . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 5.2 Ветвления . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 5.2.1 Условный оператор if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 5.2.2 Условная операция ?: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 5.3 Операторы цикла . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 5.3.1 Оператор цикла с предусловием while . . . . . . . . . . . . . . . . . . . . 65 5.3.2 Оператор цикла с постусловием do . . . . . . . . . . . . . . . . . . . . . . 66 5.3.3 Оператор цикла for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 5.4 Изменение порядка выполнения команд в машинном коде . . . . . . . . . . . . 69 5.5 Операторы перехода break, continue, goto . . . . . . . . . . . . . . . . . . . . . . 70 5.5.1 Оператор break в телах циклов . . . . . . . . . . . . . . . . . . . . . . . . 71 5.5.2 Оператор continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 5.5.3 Оператор goto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 5.6 Константные выражения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 5.7 Оператор switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 5.8 Стили оформления программ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 5.9 Примеры реализации простых алгоритмов . . . . . . . . . . . . . . . . . . . . . 83 5.9.1 Алгоритмы над фиксированным числом объектов . . . . . . . . . . . . . 83 5.9.2 Алгоритмы обработки последовательностей . . . . . . . . . . . . . . . . . 84 5.10 Задания на структурное программирование . . . . . . . . . . . . . . . . . . . . . 85 6 От описания до единиц трансляции 87 6.1 Описания и определения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 6.1.1 Видимость идентификаторов меток . . . . . . . . . . . . . . . . . . . . . 87 6.1.2 Описания и определения объектов и функций. . . . . . . . . . . . . . . . 88 6.1.3 Производные типы. Категория типов «функция». . . . . . . . . . . . . . 88 6.1.4 Блочная область видимости и автоматическое время хранения. Рекурсия. 90 6.1.5 Аппаратный стек как реализация механизма вызова функций и автома- тического времени хранения . . . . . . . . . . . . . . . . . . . . . . . . . . 92 6.1.6 Область видимости пространства имён и статическое время хранения . 95 6.1.7 Поиск имён . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 6.1.8 Инициализация . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 6.1.9 Связанность описаний функций . . . . . . . . . . . . . . . . . . . . . . . . 109 6.1.10 Спецификаторыклассапамятиstaticиextern.Анонимныепространства имён. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 6.1.11 Описания в операторах . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 6.2 Псевдонимы типов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 6.3 Возможности предварительной обработки . . . . . . . . . . . . . . . . . . . . . . 116 6.3.1 Включение других текстов . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 6.3.2 Макроподстановки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 6.3.3 Условная компиляция . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 6.4 Заголовочные файлы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 6.5 Программы из нескольких единиц трансляции . . . . . . . . . . . . . . . . . . . 124 6.6 Этапы трансляции программы на практике . . . . . . . . . . . . . . . . . . . . . 125 6.7 Встраиваемые функции. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 7 Указатели и массивы 134 7.1 Указатели на отдельные объекты . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 7.1.1 Категория типов «указатель» . . . . . . . . . . . . . . . . . . . . . . . . . 134 7.1.2 Использование указателей с функциями . . . . . . . . . . . . . . . . . . . 136 7.2 Операция sizeof . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 7.3 Простое использование массивов . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 7.3.1 Арифметика указателей . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 7.3.2 Описание и работа с массивами . . . . . . . . . . . . . . . . . . . . . . . . 140 7.3.3 Инициализаторы массивов . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 7.3.4 Массивы и функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 7.4 Комбинирование конструкций создания производных типов . . . . . . . . . . . 148 7.4.1 Массивы массивов. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 ii ОГЛАВЛЕНИЕ 7.5 Указатели на функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 7.6 Квалификаторы типов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 7.6.1 Квалификаторы параметров функций. const-корректность.. . . . . . . . 156 7.7 Расширенные константные выражения . . . . . . . . . . . . . . . . . . . . . . . . 157 7.8 Нулевой указатель. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 7.9 Строковые литералы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 7.10 Задания на массивы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 8 Динамические структуры данных 163 8.1 Сложность вычислений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163 8.1.1 Оценка алгоритмической сложности . . . . . . . . . . . . . . . . . . . . . 165 8.1.2 Сортировка массива . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 8.1.3 Двоичный поиск . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 8.2 Работа с динамической памятью . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 8.2.1 Владение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 8.2.2 Динамические массивы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176 8.2.3 Обзор линейных структур данных . . . . . . . . . . . . . . . . . . . . . . 179 8.3 Многомерные структуры данных . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 8.3.1 Шаговый доступ. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 8.3.2 Массивы указателей и «рваные» массивы . . . . . . . . . . . . . . . . . . 182 8.4 Введение в классовые типы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184 8.4.1 Имена классовых типов . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186 8.4.2 Влияние квалификаторов на структуру и её члены . . . . . . . . . . . . 187 8.4.3 Выравнивание объектов . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 8.4.4 Использование классовых типов с функциями . . . . . . . . . . . . . . . 190 8.5 Неполные типы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 8.6 Графовые структуры данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194 8.6.1 Связанные списки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196 8.6.2 Хеш-таблицы. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 8.6.3 Деревья . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 8.7 Сравнение динамических структур данных . . . . . . . . . . . . . . . . . . . . . 201 8.7.1 Комбинирование структур данных . . . . . . . . . . . . . . . . . . . . . . 202 9 Основы объектно-ориентированного программирования на языке C++ 203 9.1 Аргументы по умолчанию . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203 9.2 Последовательность стандартных преобразований . . . . . . . . . . . . . . . . . 205 9.2.1 Приведения типов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205 9.3 Перегрузка функций . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206 9.4 Временные объекты . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210 9.5 Ссылки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211 9.5.1 Ссылки на объекты . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213 9.5.2 Ссылки на функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218 9.5.3 Ссылки и перегрузка функций . . . . . . . . . . . . . . . . . . . . . . . . 218 9.6 Классовые типы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 9.6.1 Функции-члены классовых типов . . . . . . . . . . . . . . . . . . . . . . . 221 9.6.2 Статические члены классов . . . . . . . . . . . . . . . . . . . . . . . . . . 227 9.6.3 Вложенные и локальные классы . . . . . . . . . . . . . . . . . . . . . . . 229 9.6.4 Контроль доступа к членам классов . . . . . . . . . . . . . . . . . . . . . 231 9.6.5 Инициализация классов . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235 9.6.6 Специальные функции-члены . . . . . . . . . . . . . . . . . . . . . . . . . 239 9.6.7 Конструктор по умолчанию . . . . . . . . . . . . . . . . . . . . . . . . . . 240 9.6.8 Автоматическое освобождение ресурсов . . . . . . . . . . . . . . . . . . . 241 9.6.9 Копирование и перемещение объектов классовых типов . . . . . . . . . . 244 9.6.10 Размещение описаний классов . . . . . . . . . . . . . . . . . . . . . . . . . 254 9.6.11 Пользовательские преобразования типов . . . . . . . . . . . . . . . . . . 259 9.6.12 Перегрузка операций . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 9.6.13 Аргументо-зависимый поиск имён . . . . . . . . . . . . . . . . . . . . . . 265 9.6.14 Друзья классов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267 iii ОГЛАВЛЕНИЕ 10 Обобщённое программирование на языке C++ 270 10.1 Шаблоны . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270 10.1.1 Концепции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271 10.1.2 Шаблоны функций и разрешение перегрузок . . . . . . . . . . . . . . . . 272 10.1.3 Шаблоны классов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278 10.1.4 Неявнаяиявнаяинстанциацияшаблонов.Шаблоныизаголовочныефай- лы.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282 10.1.5 Явная специализация шаблонов . . . . . . . . . . . . . . . . . . . . . . . . 284 10.1.6 Частичная специализация шаблонов классов . . . . . . . . . . . . . . . . 286 10.1.7 Поиск имён в шаблонах . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288 10.2 Простые применения шаблонов . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291 10.2.1 Списки инициализации в роли аргументов . . . . . . . . . . . . . . . . . 291 10.2.2 Прозрачная передача аргументов. std::forward. Вариадические шаблоны. 292 10.2.3 std::move. Метафункции. Шаблоны псевдонимов типов . . . . . . . . . . 296 10.2.4 std::exchange . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298 10.2.5 Автоматический вывод типов в языке C++. Заполнители. Хвостовой возвращаемый тип функции . . . . . . . . . . . . . . . . . . . . . . . . . . 299 10.3 Стандартная библиотека шаблонов . . . . . . . . . . . . . . . . . . . . . . . . . . 302 10.3.1 Простые концепции. Не типовые параметры шаблонов . . . . . . . . . . 302 10.3.2 Итераторы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304 10.3.3 Черты . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309 10.3.4 Контейнеры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310 10.3.5 Последовательности. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312 10.3.6 Строки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314 10.3.7 Цикл for для диапазона . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314 10.3.8 Функциональные объекты. Лямбда-выражения . . . . . . . . . . . . . . . 315 10.3.9 Алгоритмы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320 10.3.10Ассоциативные контейнеры . . . . . . . . . . . . . . . . . . . . . . . . . . 321 11 Архитектура приложений на C++ 322 11.1 Наследование классов. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322 11.1.1 Основы наследования . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322 11.1.2 Контроль доступа при наследовании классов . . . . . . . . . . . . . . . . 327 11.1.3 Специальные члены класса и наследование . . . . . . . . . . . . . . . . . 330 11.1.4 Цепочки наследования . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332 11.1.5 Виртуальные функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333 11.1.6 Чисто виртуальные функции и абстрактные классы . . . . . . . . . . . . 338 11.1.7 Потоки ввода-вывода . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339 A Список операций языка C++ 346 Литература 348 История версий 349 iv 0. Предисловие Предисловие Данный текст предназначен для изучающих дисциплину «Языки программирования» и содержит весь материал, необходимый для успешной теоретической подготовки и написа- ния практических работ. Если вы не согласны с данным утверждением, автор настоятельно просит уведомить его об этом, чтобы недочёты и упущения оперативно исправлялись. Выделенный жирным курсивом текст обычно встречается при первом употреблении терминов вместе с их определением. Знание этих определений является основополагающим как для понимания дальнейшего материала, так и в практической работе. Для большинства терминоввскобкахдаётсяанглоязычныйвариант,чтопоможетвампричтениианглоязычной литературыисообщений,выдаваемыхпрограммами.Еслитакимобразомвыделеннетермин, а целое предложение, значит оно несёт исключительную важность. Также следует обращать особое внимание на содержимое списков. Краткиефрагментыиотдельные«слова»языковпрограммирования,атакжелюбойдру- гой текст, предназначенный для ввода в компьютер, набран моноширинным шрифтом. При описании синтаксиса некоторых конструкций, среди фиксированных элементов, набранных таким образом, могут встречаться переменные части, которые набраны обычным шрифтом. Фиксированныечастиподлежатвводувточности,какуказано,переменныечастиследуетпри использовании заменять соответствующими им по смыслу элементами программы. Нижний индекс «опц» означает, что данный элемент является опциональным. Например: return выражение ; опц Сначаласледуетзаписатьсловоreturn,являющеесяфиксированнымэлементом.Вместосло- ва «выражение» нужно ввести некоторое выражение, которое может быть опущено, что по- казано нижним индексом «опц». Вслед за этим следует записать точку с запятой, также являющуюся фиксированным элементом. Текст, выделенный чертами на полях, как этот абзац, содержит расширенную, более сложную часть материала. При первом прочтении её можно пропустить, но вернуться к ней следует обязательно перед переходом к следующей главе, чтобы, если не помнить наизусть всех хитростей, то хотя бы иметь представление о деталях и возможных про- блемах и уметь быстро находить в тексте нужный материал, когда в этом возникнет необходимость. Крупные фрагменты программ имеют своё отдельное место в тексте. Они раскрашены для улучшения зрительного восприятия, а их строки пронумерованы на полях для удобства ссылок на них: 1 int example(int& a,int b,int c) 2 { 3 // Это фрагмент текста программы, также называемый листингом. 4 a = b+c; 5 return 0; 6 } Номера строк, разумеется, к самому тексту программы не относятся. Нетривиальные по объёму фрагменты кода, не являющиеся самодостаточными программами, обычно отмеча- ются соответствующим комментарием. В примерах взаимодействия программ с пользователем приводится весь текст, как он вы- глядит на экране, при этом текст, вводимый пользователем, подчёркивается. Нажатие кла- виши Enter обозначается знаком ê. Пример: Input number: 234ê You have entered 234. v Часть I Общие сведения о языках программирования 1 1. Введение в языки программирования Глава 1 Введение в языки программирования Этоттекстпризвандатьчитателюначальныесведенияоязыкахпрограммирования,т.е.о томсредстве,котороепозволяетвоспользоватьсявычислительнымустройствомдлярешения требуемых задач. Речь идёт, разумеется, об участии в активной роли разработчика, который не только пользуется уже существующими инструментами, но и улучшает существующие, а также создаёт новые. Автор преследовал следующие цели при написании ещё одной книги по программирова- нию: • Дать читателю понимание происходящего на всех уровнях, начиная от архи- тектурыпрограммныхсистем,изаканчиваяспецификойработыцентральногопроцессора. Этокнигадлятех,ктохочетпонимать,чтоженасамомделепроисходитвнутрикомпью- тера,ипочему.Безподробногорассмотренияабстрактныхипрактическихаспектовневоз- можно объяснить разницу между «работающей» (внешне, здесь и сейчас) и «корректной» программой, которая действительно работает во всех смыслах важных для разработчи- ков, служб поддержки и конечных пользователей в рамках тех или иных требований. • Рассмотреть язык C++ в его современном варианте, зачастую кардинально от- личном от описанного в имеющейся, особенно русскоязычной, литературе. Само препо- давание этого языка, особенно в качестве первого для начинающих специалистов, часто подвергается жёсткой критике, однако автор всё равно выбрал этот путь. Во-первых, этот язык достаточно низкоуровнёвый, чтобы описание происходящего в нём на всех уровнях былодостаточнопрозрачнымилаконичнымдляизложенияначинающимпрограммистам. Отсутствие такого понимания и породило армию «шаманов», занимающих значительную долю рынка вакансий разработчиков ПО. Во-вторых, за этим языком в настоящем (и обо- зримом будущем) остаётся огромное количество кода который необходимо использовать и дорабатывать. Поэтому серьёзному специалисту никак не избежать знакомства с этим языком,аеслиэтотак,тоследуетстроитьсистемузнанийначинаяссамогонизкогоуров- ня. Овладение многими языками более высокого уровня, в первую очередь использующим тежепарадигмы,чтоиC++,послезнакомствасним,являетсяотносительнолёгкимпро- цессом,посколькуостанетсятолькодостроитьещёодинэтажабстракций,чегонескажешь об обратном процессе, что многократно подтверждалось на практике. Практически во всех аспектах своего существования язык C++ связан с языком, от кото- рогобылпроизведён—языкомC.ЯзыкCимеетменьшеечислосредств,чемC++,иимеет другие многочисленные отличия. Поскольку программисту на C++ также не избежать и встречи с C, эти различия будут приведены в приложении. • Ввести все требуемые определения в том виде, в котором они даны в стан- дарте, в том числе и на английском языке. Охватить 100% возможностей даже чистого стандарта языка данная книга пытаться не будет, поэтому необходимо с самого начала готовить читателя к чтению других источников. Кроме этого на этом языке говорят все инструментальные средства, с которым программисту предстоит вести диалог. Данный текст предполагает наличие знаний в областях математики, информатики и ан- глийского языка в рамках школьной программы. Мы будем останавливаться на необходи- мых понятиях из дисциплин «Математический анализ», «Линейная алгебра» и «Архитек- тура ЭВМ» только в необходимых для данного изложения объёме, поскольку их изучение 2 1.1. Определение языка программирования и его аспектов предполагаетсякакпроцесс,параллельныйзнакомствусрассматриваемымвэтомтекстема- териалом.Другиезатрагиваемыеобластинаукибудутотмечены,какимеющиезначимость,в соответствующих разделах, чтобы направить читателя на поиск дополнительного материала в нужном направлении. Перечислим основные из них здесь в виде целей, которые данная книга не ставит перед собой: • Детальное изучение языков ассемблера. Примеры на одном их этих языков будут приводиться с целью демонстрации связи кода наязыкеC++синструкциями,исполняемымипроцессором,ноучебникомпонемуданная книга не претендует являться. • Изложение теории языков и трансляторов. Мы познакомимся с практически полезными понятиями, необходимыми для понимания устройства конкретного языка, но рассмотрение теории, лежащей в основе построения ма- шинных языков как таковых, не входит в задачи данной книги. • Детальное рассмотрение большого количества алгоритмов и структур данных. Сколько-либо полное рассмотрение даже очень узких и специализированных вопросов в этой области легко может занять тысячи страниц. Вместо этого будет введено базовое по- нятие алгоритмической сложности и рассмотрены имеющиеся на уровне стандарта языка средства, из которых путём комбинирования можно построить удовлетворительные реше- ния для многих практических задач. Ограничив себя конечными рамками, приступим к изложению материала. 1.1. Определение языка программирования и его аспек- тов Язык программирования (ЯП) (programming language) — формальная знаковая система для планирования поведения компьютеров. Язык программирования — формальный язык (formal language), т.е. множество ко- нечныхстрокнадконечнымалфавитом.Алфавитопределяетмножествонеделимыхединиц, последовательности которых применительно к языку программирования называются про- граммами (program).Хотявбольшинствеслучаевалфавитпрограммы—символы,асама программа — текст, могут использоваться и другие представления этой формальной кон- струкции, к ней сводимые. Необязательнокаждаяпоследовательностьэлементовалфавитаотноситсякконкретному языку — для этого она также должна быть согласованной (well-formed), а именно удо- влетворятьнекоторымдополнительнымправилам(например,некаждаяпоследовательность букв естественного языка имеет в его рамках смысл). Основным способом задания формаль- ного языка является именно этот набор правил построения согласованных последователь- ностей из элементов алфавита. Чаще всего он предполагает многоэтапное построение более сложных конструкций из простых, начиная с элементов алфавита, и заканчивая целой про- граммой.Этиправилачащевсегоназываютсинтаксисом (syntax)языка,асогласованные последовательности элементов алфавита — синтаксически корректными программами. Язык программирования — знаковая система (notation), т.е. система элементов, за каждым из которых и, следовательно, за программами из них составленными в соответствие с синтаксисом языка, закреплено некоторое значение или смысл. Правила, задающие связь между синтаксически корректными элементами программы и их значением, называются се- мантикой (semantics) языка. В отличие от естественных языков, языки программиро- вания не допускают разночтений — смысл каждого элемента строг и однозначен. Придание программам однозначного смысла даёт возможность использовать их для хранения и пере- дачи информации, необходимой для планирования поведения компьютеров. Наконец, последний элемент языка программирования, который часто не обсуждается, несмотрянаегоогромнуюважность,—этопрагматика.Синтаксическихисемантическихас- пектовдостаточно,чтобыустановитьвзаимоотношениямеждуоднимчеловекомикомпьюте- ром,посколькупоследнийнеимеетцелевыхустановок,аявляетсявсеголишьисполнителем. Но язык программирования — не только средство взаимодействия человека с компьютером, но и средство взаимодействия людей друг с другом, когда речь идёт о планировании поведе- ния компьютеров. 3 1.2. История языков программирования Приведём пример: математическая запись aˆb относительно однозначна в том смысле, что соответствует умножению двух величин. Синтаксический её аспект — правила записи знака операции между двумя операндами. Семантический аспект — правила, определяющие понятие «умножение». Но какой проблеме соответствует эта запись? Поиск площади прямо- угольника по сторонам, нахождение мощности, зная ток и напряжение, расчёт общего числа предметов,знаячислокоробокипредметоввкаждойизних—вотнесколькопринципиально разных, но допустимых интерпретаций данной записи. Более того, наше предположение о том, что знак ˆ соответствует скалярному умножению, также является не беспочвенным, а следствием интуитивного поиска подходящей целевой установки. Таким образом, для уста- новления взаимопонимания между людьми, имеющими дело с одной программой, необходим контекст,впервуюочередь,одинаковыепредставленияосутирешаемойзадачи.Крометого, даже отдельные элементы программы могут нести смысл не описываемый его формальной семантикой. Без рассмотрения синтаксиса и семантики языков книге по языкам программирования обойтись не удастся, но автор будет стараться уделить не меньшее внимание и последнему, наивысшему уровню — прагматике (pragmatics), т.е. языковым средствам установления контекста, ролей и передачи целевых установок между людьми. Переоценить важность это- го аспекта невозможно, поскольку бурно развивающиеся технологии приводят к тому, что программа, которую невозможно понять для доработки и исправления ошибок, становится никому не нужной с момента её первого написания. В любом случае, программы гораздо чаще читают, нежели пишут. Отметим, что для использования в вычислительной технике разработано множество ис- кусственныхязыков,некаждыйизкоторыхявляетсяязыкомпрограммирования—ониотли- чаютсяотдругихтем,чтопредназначеныдляпланированияповедениякомпьютеровсцелью решения поставленных людьми задач. Читателю, которого интересуют другие основополагающие теоретические принципы язы- ков программирования можно порекомендовать книгу [6]. 1.2. История языков программирования Языки программирования принято разделять на несколько поколений. Точные границы и принадлежность языка программирования не всегда удаётся определить точно, особенно учитываяфактизмененияпринятойклассификациисовременем.Приведёмпримерныйплан исторического развития ЯП с указанием ключевых особенностей, на которых построена эта классификация. 1. Машинные коды (machine code). Данные языки программирования напрямую отра- жают систему команд того или иного вычислительного средства, т.е. являются специфич- ными для семейств или даже отдельных аппаратных средств. Это самый низкий уровень, которыйможетиметьязыкпрограммирования,еслинеопускатьсядовнутреннегоустрой- ства соответствующего процессора. Поскольку, фактически, каждому программируемому вычислительному устройству соответствует такой язык, выбрать «первого» представите- ля можно по-разному в зависимости от того, что же считать первым компьютером и по каким критериям. Автор предлагает в качестве примера рассмотреть электромеханиче- ский компьютер Z3, разработанный Конрадом Цузе и завершённый в 1941-м году, кото- рый являлся первым работающим в действительности (а не на бумаге) программируемым устройством. В качестве современных представителей языков программирования первого поколения приведём две наиболее распространённые в настоящее время архитектуры цен- тральныхпроцессоров:x86(почтинавернякаиспользуетсяввашемдомашнемкомпьютере) иARM(вероятнеевсегоиспользуетсяввашемсмартфоне).Формальносистемамашинных кодов описывает лишь соответствие входных данных, составляющих программу, тем или иным действиям исполнительного устройства, никак не описывая представление этих ин- струкций в пригодном для чтения человеком виде. Как следствие, вместо них даже на самом низком уровне программирования применяются языки ассемблера. 2. Языки ассемблера (assembly language). Специфической чертой этого поколения язы- ков программирования является прямое соответствие один-в-один команд этого языка и соответствующихинструкциймашинногокода.Такимобразом,языкиассемблераявляют- сяформойзаписимашинногокодавформе,читаемойчеловеком.Длякаждогомашинного языка обычно существует минимум один язык ассемблера, а для популярных архитектур — несколько. Одна из ранних ЭВМ, называемая EDSAC (1949 г.), имела мнемоническую 4

See more

The list of books you might like

Most books are stored in the elastic cloud where traffic is expensive. For this reason, we have a limit on daily download.