- •Директивы препроцессора и комментарии
- •Структура программы
- •Переменные
- •Преобразования базовых типов
- •Базовые конструкции структурного программирования
- •Оператор "выражение"
- •Операторы ветвления Условный оператор if
- •If ( выражение ) оператор_1; [else оператор_2;]
- •Оператор switch
- •Массивы
- •Функции
- •Параметры функции
- •Передача массивов в качестве параметров
- •Передача имен функций в качестве параметров
- •Параметры со значениями по умолчанию
- •Модульное программирование
- •Директивы препроцессора
- •Директива #include
- •Директива #define
- •Области действия идентификаторов
- •Внешние объявления
- •Поименованные области
- •Пространства имен стандартной библиотеки
- •Объектно ориентированное программирование
- •Наследование
- •Использование шаблонов классов
- •Достоинства и недостатки шаблонов
- •Практические примеры. Файловые потоки. Пользовательские функции
- •Пользовательские функции
- •Краткие итоги
- •Вопросы
- •Упражнения
Состав языка С++
В тексте на любом естественном языке можно выделить четыре основных элемента: символы, слова, словосочетания и предложения. Подобные элементы содержит и язык программирования, только слова называют лексемами (элементарными конструкциями), словосочетания - выражениями, а предложения - операторами.
Алфавит языка
Все тексты на языке пишутся с помощью его алфавита. Алфавит C++ включает:
прописные и строчные латинские буквы и символ подчеркивания (_), который употребляется наряду с буквами;
арабские цифры от 0 до 9;
специальные символы, например +, *, { и &;
пробельные символы - пробел, символы табуляции, символы перевода строки и формата.
Алфавит языка в стандарте называется базовым набором символов. Кроме того, существует понятие " набор символов реализации " - все множество символов, доступных на данном компьютере. Этот набор содержит базовый набор в качестве подмножества.
Из символов базового набора составляются лексемы языка и директивы препроцессора. Символы из набора реализации используются для написания комментариев. Компилятор комментарии игнорирует.
Лексемы
Существуют следующие виды лексем:
имена (идентификаторы);
ключевые слова;
знаки операций;
разделители;
литералы (константы).
Границы лексем определяются другими лексемами, такими, как разделители или знаки операций.
Лексемы языка программирования аналогичны словам естественного языка. Например, лексемами являются константа 128 (но не ее часть 12), имя Vasia, ключевое слово goto и знак операции сложения +. Из лексем составляются выражения и операторы.
Выражение задает правило вычисления некоторого значения. Например, выражение a + b задает правило вычисления суммы величин a и b.
Оператор задает законченное описание некоторого действия.
Операторы делят на исполняемые и неисполняемые, простые и составные. Исполняемые операторы задают действия над данными. Неисполняемые операторы служат для описания данных, поэтому их часто называют операторами описания или просто описаниями. Например, int a ; - это оператор описания целочисленной переменной a.
Составной оператор или блок - это группа операторов, заключенная в фигурные скобки. Блоки могут быть вложенными.
Каждый элемент языка определяется синтаксисом и семантикой. Синтаксические определения устанавливают правила построения элементов языка, а семантика определяет их смысл и правила использования.
Объединенная единым алгоритмом совокупность описаний и операторов образует программу.
Исполняемый код
Чтобы выполнить программу, требуется перевести ее на язык, понятный процессору - в машинные коды. Этот процесс состоит из нескольких этапов.
Сначала исходный текст программы обрабатывается препроцессором. Он разыскивает в тексте программы "свои" директивы (инструкции, команды), которые начинаются с символа # ("решетка"), и выполняет их. Директивы препроцессора позволяют вставить в программу тексты из других файлов, исключить из процесса компиляции фрагменты кода или выполнить замену одних фрагментов другими.
Обработанный препроцессором текст программы (в стандарте С++ он называется "единица компиляции") передается компилятору, который выполняет лексический и синтаксический анализ. На фазе лексического анализа лексический анализатор ( сканер ) последовательно просматривает поступающий на его вход поток символов, составляющих исходный текст программы, и выделяет допустимые лексемы. Их границы определяются по разделителям, пробельным символам и другим лексемам.
На фазе синтаксического анализа синтаксический анализатор (парсер) на основе грамматики языка распознает построенные из лексем выражения и операторы. При этом выявляются синтаксические ошибки. Выполняется также семантический анализ, целью которого также является обнаружение разного рода смысловых ошибок (например, таких, как повторное описание переменной) .
Если ошибок в программе не обнаружено, выполняется фаза генерации кода.Конкретный вид кода зависит от того, приложение какого типа мы создаем: Windows или . NET. Если это обычное приложение Windows, то строится объектный модуль - заготовка исполняемой программы в машинных кодах. Для приложения . NET формируется код на системно-независимом языке CIL.
Дальнейшая судьба этого кода также зависит от типа создаваемого приложения. Для обычного приложения Windows компоновщик (синонимы - линкер, редактор связей) формирует исполняемый модуль программы, подключая к объектному модулю другие объектные модули, в том числе содержащие элементы стандартных библиотек, которые используются в любой программе (например, для выполнения вывода на экран). Если программа состоит из нескольких исходных файлов, они компилируются по отдельности и объединяются на этапе компоновки. Исполняемый модуль имеет расширение . exe и запускается на выполнение обычным образом.
Приложение . NET собирается в сборку компоновщиком сборки и запускается на выполнение под управлением виртуальной машины CLR. При создании . NET -приложений также имеется возможность компилировать отдельно несколько модулей программы, собирая их потом в одну сборку.
Описание синтаксических конструкций
Для описания языка здесь используется неформальный способ, при котором необязательные части синтаксических конструкций заключаются в квадратные скобки, текст, который необходимо заменить конкретным значением, пишется по-русски, а выбор одного из нескольких элементов обозначается вертикальной чертой. Например:
[ { void | int } ] имя();
Фигурные скобки используются для группировки элементов, из которых требуется выбрать только один.
Рассмотрим лексемы языка С++.
Имена (идентификаторы)
Идентификатор - это имя программного объекта. В идентификаторе могут использоваться латинские буквы, цифры и знак подчеркивания. Прописные и строчные буквы различаются. Первым символом идентификатора может быть буква или знак подчеркивания.
Длина идентификатора по стандарту не ограничена. Идентификатор создается на этапе объявления переменной, функции, типа и т.п., после этого его можно использовать в последующих операторах программы. При выборе идентификатора необходимо иметь в виду следующее:
идентификатор не должен совпадать с ключевыми словами и именами используемых стандартных объектов языка;
не рекомендуется начинать идентификаторы с символа подчеркивания;
на идентификаторы, используемые для определения внешних переменных, налагаются ограничения компоновщика.
Ключевые слова
Ключевые слова - это зарезервированные идентификаторы, которые имеют специальное значение для компилятора. Их можно использовать только в том смысле, в котором они определены. Далее приведен список ключевых слов С++.
asm |
do |
if |
return |
typedef |
auto |
double |
inline |
short |
typeid |
bool |
dynamic _ cast |
int |
signed |
typename |
break |
else |
long |
sizeof |
union |
case |
enum |
mutable |
static |
unsigned |
catch |
explicit |
namespace |
static_cast |
using |
char |
export |
new |
struct |
virtual |
class |
extern |
operator |
switch |
void |
const |
false |
private |
template |
volatile |
const_cast |
float |
protected |
this |
wchar_t |
continue |
for |
public |
throw |
while |
default |
friend |
register |
true |
|
Знаки операций
Знак операции - это один или более символов, определяющих действие над операндами. Внутри знака операции пробелы не допускаются. Символы, составляющие знак операции, могут быть как специальными, например, &&, | и <, так и буквенными, такими как reinterpret_cast или new.
Операции делятся на унарные, бинарные и тернарную по количеству участвующих в них операндов. Большинство стандартных операций может быть переопределено (перегружено).
Константы
Константами называют неизменяемые величины. Есть логические, целые, вещественные, символьные и строковые константы. Компилятор, выделив константу в качестве лексемы, относит ее к одному из типов по ее внешнему виду. Программист может задать тип константы и явным образом.
Форматы констант, соответствующие каждому типу, приведены в таблице 1.1.
Таблица 1.1. Константы языка С++ |
||
Константа |
Формат |
Примеры |
Логическая |
Обозначается ключевым словом true или false |
true, false |
Целая |
Десятичный: последовательность десятичных цифр, начинающаяся не с нуля, если это не число нуль |
8, 0, 199226 |
|
Восьмеричный: нуль, за которым следуют восьмеричные цифры (0, 1, 2, 3, 4, 5, 6, 7) |
01, 020, 07155 |
|
Шестнадцатеричный: 0х или 0Х, за которым следуют шестнадцатеричные цифры (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F) |
0xA, 0x1B8, 0X00FF, 0X00ff |
Вещественная |
Десятичный: [цифры].[цифры] |
5.7, 0.001, 35 |
|
Экспоненциальный: [цифры][.][цифры]{E|e}[+|-][цифры] |
0.2E6, .11e-3, 5E10, 1.22E-10 |
Символьная |
Один или более символов, заключенных в апострофы |
'A', 'ю', '*', 'db', 'A', '\n', '\012', '\x07\x07' |
Строковая |
Последовательность символов, заключенная в кавычки |
"Здесь был Vasia", "\tСумма =\xF5\n" |
Допустимые диапазоны значений целых и вещественных констант приведены в таблице 1.2.
Таблица 1.2. Диапазоны значений основных типов данных для IBM PC |
||
Тип |
Диапазон значений |
Размер (байт) |
bool |
true и false |
1 |
signed char |
-128 … 127 |
1 |
unsigned char |
0 … 255 |
1 |
signed short int |
-32 768 … 32 767 |
2 |
unsigned short int |
0 … 65 535 |
2 |
signed int |
-2 147 483 648 … 2 147 483 647 |
4 |
unsigned int |
0 … 4 294 967 295 |
4 |
signed long int |
-2 147 483 648 … 2 147 483 647 |
4 |
unsigned long int |
0 … 4 294 967 295 |
4 |
float |
3.4e-38 … 3.4e+38 |
4 |
double |
1.7e-308 … 1.7e+308 |
8 |
long double |
3.4e-4932 … 3.4e+4932 |
10 |
Если требуется сформировать отрицательную целую или вещественную константу, то перед ней ставится знак унарной операции изменения знака (-), например, -218.
Вещественная константа в экспоненциальном формате представляется в виде мантиссы и порядка. Значение константы определяется как произведение мантиссы и возведенного в указанную в порядке степень числа 10 (например, 1.3e12 это 1,3 * 1012). При записи вещественного числа могут быть опущены либо целая часть, либо дробная, но, конечно, не обе сразу. Пробелы внутри числа не допускаются.
Символьный литерал - это один или более символов, заключенных в одиночные кавычки (апострофы). Внутри апострофов можно задать любой символ из набора символов реализации. Пустая символьная константа недопустима.
Если перед символьным литералом указан символ L, то литерал называется широким.Если L отсутствует, литерал называется обычным, или узким. Обычный символьный литерал имеет тип char, широкий - тип wchar_t (о типах - далее в этой лекции).
Некоторые символы набора реализации являются непечатаемыми.Они предназначены для управления процессом отображения печатаемых символов на экране или принтере. Для представления в программе непечатаемых символов используется управляющая последовательность ( escape sequence ) -последовательность символов, начинающаяся с обратной косой черты \ ( backslash ). Кроме того, символы ' (апостроф), " (кавычки), ? (вопрос) и сама обратная косая черта являются специальными символами и также представляются в виде управляющих последовательностей.
В общем виде управляющая последовательность может быть задана в двух формах:
\000
\xhhh
Здесь 000 представляет собой последовательность от одной до трех восьмеричных цифр, а hhh - последовательность от одной до трех шестнадцатеричных цифр, которая задает код символа. При выводе кода символа на принтер или экран вместо кода изображается печатаемый символ или выполняется определяемое кодом действие (например, перевод курсора на следующую строку).
Допустимые значения кодов ooo ( hhh ) определяются реализацией. Коды обычных символов и широких символов различаются. Нулевой символ '\0' (L'\0' для широких) является обязательным в составе набора символов реализации, поскольку играет особую роль в представлении строковых литералов.
В строковых литералах также допускается задавать любые символы из набора символов реализации, в том числе и управляющие последовательности. Например, если внутри строки требуется записать кавычку, ее предваряют косой чертой, по которой компилятор отличает ее от кавычки, ограничивающей строку:
"Издательский дом \"Питер\""
Тем не менее, апостроф разрешается задавать без обратной косой черты, например:
"Издательский дом 'Питер'"
Строковые константы, отделенные в программе только пробельными символами, при компиляции объединяются в одну.
Длинную строковую константу можно разместить на нескольких строках программы, используя в качестве знака переноса обратную косую черту, за которой следует перевод строки. Эти символы игнорируются компилятором, при этом следующая строка программы воспринимается как продолжение предыдущей. Например, строка
"Никто не доволен своей \
внешностью, но каждый доволен \
своим умом"
эквивалентна строке
"Никто не доволен своей внешностью, но каждый доволен своим умом"
Кавычки пишутся только в начале и в конце многострочного литерала.
Строковые литералы так же, как и символьные, подразделяются на обычные (узкие) и широкие.
Директивы препроцессора и комментарии
Директивы препроцессора предназначены для обработки исходного текста программы перед компиляцией. Любая директива должна начинаться с символа #. На каждой строке может располагаться только одна директива. Например, по директиве
#include "myfile"
в текст программы будет вставлено содержимое так называемого заголовочного файла с именем myfile. Заголовочные файлы содержат различную информацию, необходимую для успешной компиляции программы.
Комментарии предназначены для записи пояснений к программе. В С++ есть два вида комментариев: однострочные и многострочные. Первый вид начинается с двух символов // ("прямая косая черта") и занимает одну строку. Второй вид комментариев начинается с двух символов /* и завершается двумя символами */.
Внутри комментария можно использовать любые символы из набора реализации. Внутри многострочного комментария можно размещать однострочный комментарий.
Типы данных С++
Основная цель любой программы состоит в обработке данных. Данные, с которыми работают машинные команды, хранятся в оперативной памяти. Компилятору для формирования команд необходимо точно знать, сколько места занимают данные, как именно закодированы и какие действия с ними можно выполнять. Все это задается при описании данных с помощью типа. Каждая константа, переменная, результат вычисления выражения или функции должны иметь конкретный тип.
Тип данных однозначно определяет:
множество их возможных значений (связанное с внутренним представлением данных в памяти компьютера);
допустимые действия над данными (операции и функции).
Программист задает тип каждой величины, используемой в программе, исходя из характеристик реальных объектов, которые представляют эти величины. Обязательное указание типа позволяет компилятору проверять, правильно ли используется объект в конструкциях языка. От типа величины зависят машинные команды, которые будут использоваться для обработки данных.
Объем памяти, выделяемый для величин, тоже зависит от типа. По стандарту единицей памяти в С++ является байт.
Типы языка С++ делятся на элементарные (базовые, основные) и составные. Элементарные типы данных являются неделимыми и позволяют описывать целые, вещественные, символьные и логические величины. На основе этих типов программист может конструировать составные типы. Составной тип - это тип, определенный в терминах другого типа. К составным типам относятся массивы, структуры, объединения, перечисления, ссылки, указатели и классы. Внутреннее представление данных всех типов, их размеры и диапазоны величин определяются конкретной платформой.
Рисунок 1.1 помогает окинуть взглядом все разнообразие типов данных, определенных в стандарте языка С++.
Рис. 1.1. Типы данных стандартного С++
Базовые типы данных
Элементарные типы данных, если исключить из них тип void, часто называют арифметическими,поскольку их можно использовать в арифметических операциях. Для их описания определены следующие ключевые слова:
bool (логический);
char (символьный);
wchar_t (широкий символьный);
int (целый);
float (вещественный);
double (вещественный с двойной точностью).
Первые четыре типа называют интегральными (целыми), последние два - типами с плавающей точкой. Код, который формирует компилятор для обработки целых величин, отличается от кода для величин с плавающей точкой.
Существует четыре ключевых слова, уточняющих внутреннее представление и диапазон значений стандартных типов:
short (короткий);
long (длинный);
signed (знаковый);
unsigned (беззнаковый).
Сочетания перечисленных ключевых слов формируют 14 различных арифметических типов, приведенных на рис. 1.1. Например, char, signed char и unsigned char - это три равноправных различных типа.
ПРИМЕЧАНИЕ
Во многих других языках символьные типы более четко отделены от арифметических. В С++ символы фактически являются подмножеством целых величин и могут участвовать в арифметических операциях. По этой причине типы signed char и unsigned char встречаются на рисунке дважды: как символьные и как целые типы. Это соответствует описанному в стандарте.
Логический тип
Величины логического типа могут принимать только значения true и false, являющиеся ключевыми словами. Величины логического типа могут участвовать в арифметических операциях. При преобразовании к целому типу true имеет значение 1, false - нуль. Размер логического типа в стандарте не определен и зависит от реализации.
Символьные типы
В стандарте языка определено три различных символьных типа: char, signed char и unsigned char. Внутренним представлением символа является его код - целое число. Под величину любого символьного типа отводится одна единица памяти - байт:
sizeof(char) = sizeof(signed char) = sizeof(unsigned char) = 1
Размер байта зависит от реализации, однако этот размер должен быть достаточен, чтобы вместить код любого символа из набора символов реализации для данного компьютера. Наличие знака у типа char тоже зависит от реализации: он может совпадать либо с signed char, либо с unsigned char.
Величины символьных типов применяются также для хранения целых чисел, не превышающих границы указанных диапазонов, и могут участвовать в арифметических операциях, поэтому их также относят к целым типам.
Целые типы
В языке С++ определено 8 типов для хранения целочисленных величин: четыре знаковых ( signed char, short int, int, long int ) и четыре беззнаковых ( unsigned char, unsigned short int, unsigned int, unsigned long int ). По умолчанию все целочисленные типы считаются знаковыми, поэтому спецификатор signed можно не указывать. Ключевое слово unsigned позволяет представлять неотрицательные целые числа.
ПРИМЕЧАНИЕ
Типы short int, long int, signed int и unsigned int можно сокращать до short, long, signed и unsigned соответственно.
Целым константам, встречающимся в программе, по умолчанию приписывается тип signed int. Если он по каким-либо причинам не устраивает программиста, можно явно указать требуемый тип с помощью суффиксов L, l ( long ) и U, u ( unsigned ). Например, константа 32L будет иметь тип long и занимать 4 байта. Можно использовать суффиксы L и U одновременно, например, 0x22UL или 05Lu.
Размеры и диапазоны целых типов зависят от реализации. Все, что определяет стандарт по поводу размера этих типов - каждый последующий тип в каждой четверке занимает не меньше памяти, чем предыдущий:
sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long).
При этом сказано, что тип int должен иметь естественный размер, обеспечиваемый архитектурой компьютера. Диапазоны значений величин целых типов для IBM PC -совместимых компьютеров приведены в таблице 1.2.
Visual С++.NET 2005 предоставляет несколько нестандартных целых типов. Например, тип long long определяет целые числа в диапазоне от -9 223 372 036 854 775 808 до +9 223 372 036 854 775 807 и занимает в памяти 8 байт.
Типы с плавающей точкой
Стандарт С++ определяет три типа данных для хранения вещественных значений: float, double и long double. Все они имеют знак.
Внутреннее представление вещественного числа состоит из мантиссы и порядка. Длина мантиссы определяет точность числа, а длина порядка - его диапазон.
Константы с плавающей точкой имеют по умолчанию тип double. Можно явно указать тип константы с помощью суффиксов F, f ( float ) и L, l ( long ). Например, константа 2E+6L имеет тип long double.
Для вещественных типов в таблице приведены абсолютные величины минимальных и максимальных значений.
Тип void
Тип void используется для определения функций, которые не возвращают значения, для указания пустого списка аргументов функции, как базовый тип для указателей и в операции приведения типов.
