Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lektsii_po_si.doc
Скачиваний:
13
Добавлен:
12.11.2018
Размер:
11.78 Mб
Скачать

1.1. Языки программирования С и C++

Триумфальное шествие языка С началось с появления его компилятора для персональных компьютеров (ПК). Всего несколько лет назад этот язык высокого уровня был известен лишь узкому кругу специалистов. Тем не менее этот неизвестный язык, оста­вив позади модные языки, получил широкое распространение. Большинство популярных коммерческих программ написаны, если не исключительно, то по меньшей мере частично на языке С. Например, dBase, Word, PageMaker, PC-DOS или Sidekick.

В противоположность другим языкам высокого уровня, таким как Pascal или Basic, которые разрабатывались в университетах как учебные языки, язык С возник из реальных проблем и предназна­чался для решения конкретных практических задач. Его создате­лям — Брайану Кернигану (Brian W. Kernighan) и Деннису Ритчи (Dennis M. Ritchie) — был необходим язык для системного про­граммирования, который создавал бы быстродействующий и компактный код и, кроме того, был бы мобильным настолько, на­сколько это возможно. Язык должен был обладать возможностя­ми действительно языка высокого уровня, поскольку выяснилось, что применение языков низкого уровня (Ассемблера) при разра­ботке больших программных проектов приводит к нечитабельнос­ти программ, которые к тому же являются абсолютно немобиль­ными. Поставленная задача создателями языка решена чрезвы­чайно успешно.

Расширение языка С в соответствии с объектно-ориентированной концепцией реализовано Бьорном Страуструпом (Bjarne Stroustrup). Именно расширение, потому что совместимость с С является отличительной чертой C++. Промежуточный вариант между С и C++ назывался «С с классами». В 1985 году появилась версия, с помощью которой стала возможна реализация объектно-ориенти­рованного подхода в программировании. Эта версия получила из­вестность под именем C++. За прошедшее время язык C++ принял законченную форму и стал столь же совершенным, как и С. Одним из основных принципов, лежащих в основе C++, является его практически полная совместимость с С, которая существенно облегчила переход программистов, работавших на языке С, к объектно-ориентированному программированию и гарантирова­ла применимость существующих С-кодов.

С другой стороны, C++ можно рассматривать как определенную версию С в противоположность таким полностью объектно-ори­ентированным языкам, как Модула или Смоллток. Поэтому про­граммирование на C++ не может автоматически приравниваться к объектно-ориентированному программированию.

1.2. Отличительные признаки

Язык С с самого начала создавался как язык высокого уровня для системного программирования и предназначался, главным обра­зом, для развития операционных систем. Поскольку С разраба­тывался как встроенное системное средство, то создаваемый им код должен был достаточно просто компилироваться и иметь вы­сокое быстродействие. Таким образом, появился язык, который отличался:

  • небольшим количеством элементов языка;

  • высокой скоростью выполнения написанных на нем про­грамм;

  • поддержкой модульного программирования;

  • хорошей мобильностью наряду с возможностью работы на «нижнем уровне» (с компонентами аппаратной среды).

С развитием вычислительной техники время вычислений стано­вится все дешевле, а затраты на программирование возрастают.

Лексема - единица текста программы, которая при компиляции воспринимается как единое целое и по смыслу не может быть разделена на более мелкие элементы.

Алфавит – совокупность допустимых в языке символов или групп символов.

В языке Турбо Паскаль все компоненты формируются из множества символов стандарта ASCII, которые задаются кодами от 0 до 255.

Элементы алфавита:

Алфавит.

В алфавит языка Си входят:

• прописные и строчные буквы латинского алфавита (A,B,...,Z, a, b,..., z)

• цифры: 0,1,2,3,4,5,6,7,8,9

• специальные знаки: “ , {} | [] ( ) + - / % \ ; ‘ . : ? < = > _ & * # ~ ^

• неизображаемые символы ("обобщенные пробельные символы"), используемые для отделения лексем друг от друга (например, пробел, табуляция, переход на новую строку).

В комментариях, строках и символьных константах могут использоваться и другие литеры (например, русские буквы).

Комментарий формируется как последовательность знаков (символов), ограниченная слева знаками /*, а справа - знаками */. Например:

Объявления и определения

Главная задача любой программы состоит в обработке данных. Во время выполнения программы эти данные размещаются в различных местах оперативной памяти. Для корректного использования данных без указания адресов в явном виде применяют переменные.

Переменные представляют собой имена областей памяти, в которых находятся данные определённых типов. С помощью таких имен можно записывать (считывать) данные в область (из области) памяти.

В зависимости от вида данных для них могут применяться переменные различных типов. Типы данных определяют внутреннее представление данных в вычислительных машинах; диапазон значений, которые может принимать переменная, а также операции, в которых могут использоваться переменные указанного типа.

При разработке программы необходимо объявить используемые в ней элементы (переменные, функции, структурированные типы и т.д.) и определиться в правилах. Понятия «объявление» и «определение» часто употребляются как синонимы, хотя они означают различные процедуры.

Объявление:

  • Объявление означает задание компилятору имен (идентификаторов) переменных, функций, классов, структурированных типов или меток.

  • С помощью объявления переменной задается её тип, класс памяти и область видимости идентификатора.

  • Объявление резервирует память.

  • Идентификатор может неоднократно объявляться в рамках своей области видимости, при этом все предыдущие объявления не учитываются.

Структура и компоненты простой программы

Ранее были рассмотрены лексемы языка, способы определения констант и переменных, правила записи и вычисления выражений. Несколько слов было сказано об операции присваивания, об операторе присваивания и о том, что каждое выражение превращается в оператор, если в конце выражения находится разделитель "точка с запятой". Сейчас перейдем собственно к программированию, т.е. рассмотрим операторы, введем элементарные средства ввода-вывода, опишем структуру однофайловой программы и на несложных примерах вычислительного характера продемонстрируем особенности программирования на языке Си.

Текст программы и препроцессор.

Текст программы и препроцессор. Каждая программа на языке Си есть последовательность препроцессорных директив, описаний и определений глобальных объектов и функций. Препроцессорные директивы (#include и #define) управляют преобразованием текста программы до ее компиляции. Определения вводят функции и объекты. Объекты необходимы для представления в программе обрабатываемых данных. Функции определяют потенциально возможные действия программы. Описания уведомляют компилятор о свойствах и именах тех объектов и функций, которые определены в других частях программы (например, ниже по ее тексту или в другом файле).

Программа на языке Си должна быть оформлена в виде одного или нескольких текстовых файлов. Текстовый файл разбит на строки. В конце каждой строки есть признак ее окончания (плюс управляющий символ перехода к началу новой строки). Просматривая текстовый файл на экране дисплея, мы видим последовательность строк, причем признаки окончания строк невидимы, но по ним производится разбивка текста редактором.

Определения и описания программы на языке Си могут размещаться в строках текстового файла достаточно произвольно (в свободном формате.) Для препроцессорных директив существуют ограничения. Во-первых, препроцессорная директива обычно размещается в одной строке, т.е. признаком ее окончания является признак конца строки текста программы. Во-вторых, символ '#', вводящий каждую директиву препроцессора, должен быть первым отличным от пробела символом в строке с препроцессорной директивой

Подробному изучению возможностей препроцессора и всех его директив будет далее. Сейчас достаточно рассмотреть только основные принципы работы препроцессора и изложить общую схему подготовки исполняемого модуля программы, написанной на языке Си. Исходная программа, подготовленная на языке Си в виде текстового файла, проходит три обязательных этапа обработки (рис. 2.1):

• препроцессорное преобразование текста;

• компиляция;

• компоновка (редактирование связей или сборка).

Рис. 2.1. Схема подготовки исполняемой программы

Только после успешного завершения всех перечисленных этапов формируется исполняемый машинный код программы.

Задача препроцессора - преобразование текста программы до ее компиляции. Правила препроцессорной обработки определяет программист с помощью директив препроцессора. Каждая препроцессорная директива начинается с символа '#'. В этой главе нам будет достаточно двух директив:

#include и #define.

Препроцессор "сканирует" исходный текст программы в поиске строк, начинающихся с символа '#'. Такие строки воспринимаются препроцессором как команды (директивы), которые определяют действия по преобразованию текста. #define указывает правила замены в тексте.

# include определяет, какие текстовые файлы нужно включить в этом месте текста программы.

Директива #include <...> предназначена для включения в текст программы текста файла из каталога "заголовочных файлов", поставляемых вместе со стандартными библиотеками компилятора. Каждая библиотечная функция, определенная стандартом языка Си, имеет соответствующее описание (прототип библиотечной функции плюс определения типов, переменных, макроопределений и констант) в одном из заголовочных файлов. Список заголовочных файлов для стандартных библиотек определен стандартом языка.

Важно понимать, что употребление в программе препроцессорной директивы

#include < имя_заголовочного_файла >

не подключает к программе соответствующую стандартную библиотеку. Препроцессорная обработка выполняется на уровне исходного текста программы. Директива #include только позволяет вставить в текст программы описания из указанного заголовочного файла. Подключение к программе кодов библиотечных функций (см. рис. 2.1) осуществляется только на этапе редактирования связей (этап компоновки), т.е. после компиляции, когда уже получен машинный код программы. Доступ к кодам библиотечных функций нужен только на этапе компоновки. Именно поэтому компилировать программу и устранять синтаксические ошибки в ее тексте можно без стандартной библиотеки, но обязательно с заголовочными файлами.

Здесь следует отметить еще одну важную особенность. Хотя в заголовочных файлах содержатся описания всех стандартных функций, в код программы включаются только те функции, которые используются в программе. Выбор нужных функций выполняет компоновщик на этапе, называемом "редактирование связей".

Термин "заголовочный файл" (header file) в применении к файлам, содержащим описания библиотечных функций стандартных библиотек, не случаен. Он предполагает включение этих файлов именно в начало программы. Мы настоятельно рекомендуем, чтобы до обращения к любой функции она была определена или описана в том же файле, где помещен текст программы. Описание или определения функций должны быть "выше" по тексту, чем вызовы функций. Именно поэтому заголовочные файлы нужно помещать в начале текста программы, т.е. заведомо раньше обращений к соответствующим библиотечным функциям.

Хотя заголовочный файл может быть включен в программу не в ее начале, а непосредственно перед обращением к нужной библиотечной функции, такое размещение директив #include <...> не рекомендуется.