- •Директивы препроцессора и комментарии
- •Структура программы
- •Переменные
- •Преобразования базовых типов
- •Базовые конструкции структурного программирования
- •Оператор "выражение"
- •Операторы ветвления Условный оператор if
- •If ( выражение ) оператор_1; [else оператор_2;]
- •Оператор switch
- •Массивы
- •Функции
- •Параметры функции
- •Передача массивов в качестве параметров
- •Передача имен функций в качестве параметров
- •Параметры со значениями по умолчанию
- •Модульное программирование
- •Директивы препроцессора
- •Директива #include
- •Директива #define
- •Области действия идентификаторов
- •Внешние объявления
- •Поименованные области
- •Пространства имен стандартной библиотеки
- •Объектно ориентированное программирование
- •Наследование
- •Использование шаблонов классов
- •Достоинства и недостатки шаблонов
- •Практические примеры. Файловые потоки. Пользовательские функции
- •Пользовательские функции
- •Краткие итоги
- •Вопросы
- •Упражнения
Структура программы
Программа на языке С++ состоит из функций, описаний и директив препроцессора. О директивах мы говорили выше. Функция - это законченный фрагмент кода, к которому можно обратиться по имени (вызвать функцию). Функция может получать аргументы и возвращать в вызывающий код вычисленное в ней значение. Например, вызов функции, вычисляющей синус угла, может выглядеть примерно так же, как в математике: y = sin(x);.
Одна (и только одна) функция программы должна иметь имя main. Выполнение программы начинается с первого оператора этой функции. Ее вызывает на выполнение исполняющая система.
Описания представляют собой определения и объявления элементов программы: переменных, функций, классов, типов и т. д. Любой элемент программы должен быть определен только один раз. Это правило в стандарте называется правилом одного определения ( one definition rule, или odr ) . Объявление может встречаться в программе столько раз, сколько необходимо.
ПРИМЕЧАНИЕ
Такие требования естественны: ведь определения требуют от компилятора конкретных действий (например, выделения памяти), а объявления служат для информации.
Итак, программа, состоящая из одного модуля, имеет следующую структуру:
директивы препроцессора
описания
int main()
{
операторы главной функции
}
В общем случае программа состоит из нескольких модулей, каждый из которых может содержать все рассмотренные элементы.
Переменные
Любая программа работает с данными. В простейшем случае данные хранят в переменных. Переменная - это именованная область памяти компьютера, у переменной есть тип, имя и значение. Имя служит для обращения к области памяти, в которой хранится значение, тип определяет диапазон значений и допустимые операции. Во время выполнения программы значение переменной можно изменять.
Перед использованием любая переменная должна быть определена. Пример описания целой переменной с именем a и вещественной переменной: x
int a; float x;
В общем случае описание переменной задает не только ее имя и тип, но и другие характеристики, например, начальное значение, область действия и время жизни. Кроме того, имеет значение и место размещения описания в тексте программы.
Область действия имени - это часть программы, в которой его можно использовать для доступа к связанной с ним области памяти. В зависимости от области действия переменная может быть локальной или глобальной.
Если переменная определена внутри блока (блок ограничен фигурными скобками), она называется локальной, область ее действия - от точки описания до конца блока, включая все вложенные блоки. Если переменная определена вне любого блока, она называется глобальной и областью ее действия считается модуль, в котором она определена, от точки описания до его конца. Имя переменной должно быть уникальным в своей области видимости.
Глобальные переменные нужно стремиться использовать как можно реже. Переменная должна иметь минимальную из возможных областей видимости и действия, поскольку это значительно облегчает поиск ошибок.
Время жизни глобальных и локальных переменных отличается: глобальная переменная "живет", пока работает программа, а локальная - только до конца блока.
Кроме времени жизни и области действия, имя переменной обладает также областью видимости. Область видимости имени - часть текста программы, в которой имя можно явно использовать. Чаще всего область видимости совпадает с областью действия. Исключением является ситуация, когда во вложенном блоке определена переменная с таким же именем, что и у переменной вне блока. В этом случае внешняя переменная во вложенном блоке невидима, хотя он и входит в ее область действия. Тем не менее к этой переменной, если она глобальная, можно обратиться, используя операцию доступа к области видимости::.
Рассмотрим общий вид оператора описания переменных:
[класс_памяти] [const] тип имя [инициализатор];
Начнем с инициализатора. С его помощью можно присвоить переменной начальное значение ( инициализировать переменную ) .Инициализатор можно записывать в двух формах - со знаком равенства:
= выражение
или в круглых скобках:
( выражение )
Выражение должно быть вычисляемым на момент выполнения оператора, например:
short int a = 1;
short int b( a + 1 );
Первая форма инициализации чаще применяется для переменных базовых типов, вторая - для экземпляров классов. Если тип инициализирующего значения не совпадает с типом переменной, выполняются преобразования типа (о преобразованиях типа - в конце этой лекции).
Модификатор const показывает, что данное описание определяет не переменную, а именованную константу. Константа должна быть обязательно инициализирована при объявлении. Ключевое слово const можно задавать как перед типом, так и после него.
В одном операторе можно определить несколько величин одного типа, разделяя их запятыми. Примеры:
const char C = 'C',
X = '|'; // символьные константы С и X
int const y = 56; // целая константа y
char s, sf = 'f'; // инициализация относится только к sf
char t (54);
float c = 0.22, x(3), sum;
Класс памяти задается явным образом или по контексту описания переменной. Если он не задан явно, и переменная описана внутри блока (в частности, внутри функции main ), она считается автоматической. Память под нее выделяется при входе в блок и при необходимости инициализируется каждый раз при выполнении оператора, содержащего ее определение. Освобождение памяти происходит при выходе из блока, в котором описана переменная. Иными словами, сколько раз выполняется блок, столько раз "рождается" и "умирает" локальная переменная. Время ее жизни - с момента входа в блок и до выхода из блока.
Класс памяти static задает статическую переменную. Время ее жизни равно времени работы программы (как у глобальных переменных), а инициализируется она один раз при первом выполнении оператора, содержащего определение переменной. В зависимости от расположения оператора описания статические переменные могут быть глобальными и локальными. Глобальные статические переменные видны только в модуле, в котором они описаны.
Ключевое слово extern хотя и относится в стандарте к спецификаторам класса памяти, на самом деле служит для объявления переменной. Переменная, описанная как extern, должна быть определена в другом месте программы (как правило, в другом модуле). Объявление переменной может задаваться в программе несколько раз, а определение должно быть единственным. В отличие от определения, объявление переменной не должно содержать инициализатора - это запрещено стандартом. Фактически это просто объявление имени в данной области видимости.
Спецификатор extern может задаваться и в определении переменной, но при этом переменная обязательно должна быть проинициализирована, например:
extern double PI = 3.1415926; // это определение переменной PI
В одномодульной программе использовать объявление переменной не имеет смысла, хотя это и не запрещено стандартом. Рассмотрим примеры описаний.
int a; // 1 глобальная переменная a
int main() // 2
{ int b; // 3 локальная переменная b
static int c; // 4 локальная статическая переменная c
a = 1; // 5 присваивание глобальной переменной
int a; // 6 локальная переменная a
a = 2; // 7 присваивание локальной переменной
::a = 3; // 8 присваивание глобальной переменной
extern int x; // 9 переменная х объявлена; определение дальше
...
return 0; // 10
} // 11
int x = 4; // 12 определение и инициализация x
Здесь глобальная переменная a определена вне всех блоков, областью ее действия является вся программа. Переменная создается при запуске программы и уничтожается при окончании ее работы. Область видимости переменной - вся программа, кроме строк 6-10, так как в первой из них определяется локальная переменная с тем же именем, область действия которой начинается с точки ее описания и заканчивается при выходе из блока.
Переменные b и c - локальные, область их видимости (и действия) - блок, но время жизни различно: переменная b "рождается" при входе в блок и "умирает" при выходе из него, а переменная c, как и глобальная переменная a, создается при запуске программы и существует все время, пока работает программа.
Переменная х является глобальной и определена после тела функции main. Область действия - вся программа, однако выше точки определения переменная не видна. Чтобы иметь к ней доступ внутри тела функции, переменная объявлена как extern (строка 9).
Если при определении переменных их начальные значения явным образом не заданы, глобальные и статические переменные инициализируются по умолчанию нулевым значением соответствующего типа. Автоматические (локальные) переменные не инициализируются.
Простейшие средства ввода/вывода
Любая программа каким-либо образом взаимодействует с внешним миром. В простейшем случае это работа с консолью: ввод с клавиатуры и вывод на экран. В языке С++ нет встроенных средств ввода/вывода - он осуществляется с помощью средств, содержащихся в стандартных библиотеках. Рассмотрим два примера.
// используются классы стандартной библиотеки
#include <iostream> // 1
using namespace std; // 2
int main() // 3
{ const double course = 35.8; // 4
double sum; // 5
cout << "Введите сумму в рублях:\n"; // 6
cin >> sum; // 7
double euro = sum / course; // 8
cout << "В рублях: " << sum
<< " В евро: " << euro
<< "\n"; // 9
return 0; // 10
}
Листинг 2.1. Программа перевода рублей в европейскую валюту
Это первый пример законченной программы, поэтому рассмотрим его подробно. В первой строке записана директива препроцессора. Директива вида
#include <имя_файла>
вставляет содержимое указанного файла (он называется заголовочным ) в ту точку исходного файла, где она расположена. В данном случае директива задает включение файла <iostream>, в котором содержатся описания используемых в программе элементов стандартной библиотеки ввода/вывода.
Строка 2 является описанием, по которому программе становятся доступными все имена, определенные в стандартном заголовочном файле <iostream>. Дело в том, что внутри этого файла все описания спрятаны в так называемую поименованную область (пространство имен) с именем std. Это касается всех стандартных заголовочных файлов и сделано для того, чтобы стандартные имена не конфликтовали с теми, которые ввел программист.
Конечно, открытие всех стандартных имен из заголовочного файла не может предотвратить подобный конфликт, но есть средства, позволяющие сделать доступными не все, а только нужные имена. Они будут рассмотрены позже.
ПРИМЕЧАНИЕ
Для многих заголовочных файлов, содержимое которых определено в пространстве имен std, существуют их двойники "старого стиля" с расширением .h,описания, находящиеся в которых, доступны без дополнительных усилий - например, <iostream.h>, <stdio.h>. Заголовочные файлы, унаследованные из языка С, записываются при этом без ведущей буквы c. Этот способ использования заголовочных файлов считается устаревшим.
Строка 3 представляет собой заголовок главной (и единственной) функции, в строках 4 и 5 описаны две величины с плавающей точкой: константа course и переменная sum. Строка 6 является приглашением к вводу. В результате выполнения этого оператора на экран выводится строка "Введите сумму в рублях:" и курсор переводится на следующую строку в соответствии с управляющей последовательностью \n. Стандартному объекту cout с помощью операции << передается то, что мы хотим вывести, в данном случае строковый литерал. Для вывода нескольких элементов используется цепочка операций, как в строке 9. Все величины, кроме символов и строк, при выводе преобразуются из внутренней формы представления в последовательность символов. Под величину отводится ровно столько позиций, сколько требуется для ее вывода.
В процессе ввода ( строка 7 ) происходит обратный процесс: величина преобразуется из последовательности символов, набранных на клавиатуре, во внутреннее представление числа с плавающей точкой и помещается в ячейку памяти, зарезервированную для переменной sum. Как видите, семантика ввода проста и интуитивно понятна: значение со стандартного ввода передается в переменную, указанную справа от знака операции. Если требуется ввести несколько величин, используется цепочка операций >>.
В строке 8 определяется переменная euro, которая инициализируется результатом деления переменной sum на переменную course. В строке 10 в вызывающую среду возвращается значение 0 - признак успешного завершения программы. Оператор return 0 в главной функции записывать не обязательно, поскольку при его отсутствии значение 0 будет возвращено автоматически. Во всех последующих примерах этот оператор опущен для экономии места.
Другой вариант записи той же программы приведен в листинге 2.2.
// используются функции ввода/вывода в стиле С
#include <сstdio> // 1
using namespace std; // 2
int main() // 3
{ const double course = 36.5; // 4
double sum; // 5
printf( "Введите сумму в рублях\n" ); // 6
scanf( "%lf", &sum ); // 7
double euro = sum / course; // 8
printf( "В рублях: %lf В евро: %lf\n", sum, euro ); // 9
}
Листинг 2.2. Программа перевода рублей в европейскую валюту
По директиве препроцессора, расположенной в первой строке, в текст программы вставляется заголовочный файл <cstdio>, содержащий описание использованных в программе функций ввода/вывода. Функция printf в строке 6 выводит приглашение "Введите сумму в рублях:" и переходит на новую строку в соответствии с управляющей последовательностью \n. Функция scanf в строке 7 заносит введенное с клавиатуры число в переменную sum. Знак & обозначает операцию получения адреса переменной sum. Это нужно чтобы функция scanf могла записать в эту переменную введенное с клавиатуры значение.
Формат основных функций ввода-вывода, унаследованных из С:
int scanf ( строка_формата, список адресов вводимых величин ) // ввод
int printf( строка_формата, список выводимых величин ) // вывод
Функции выполняют форматированный ввод и вывод произвольного количества величин в соответствии со строкой формата. Она содержит символы, которые копируются на экран при выводе или запрашиваются с клавиатуры при вводе, и спецификации преобразования, начинающиеся со знака %, которые при вводе и выводе заменяются конкретными величинами. Каждой величине должна соответствовать своя спецификация.
Спецификация %d означает целое десятичное число, %f используется для величин типа float, %lf - для величин типа double. Оператор в строке 9 выводит на экран указанную в нем строку, заменив спецификации преобразования %lf на значения переменных sum и euro.
Для каждой программы необходимо выбрать один из способов вывода (либо с помощью классов, либо с помощью функций), поскольку смешивать оба варианта не рекомендуется. Функции ввода/вывода в стиле С имеет смысл использовать в тех программах, где требуется тщательное форматирование результатов, а классы - в остальных случаях.
Особенности вывода кириллицы
Задача вывода русских букв в консольное окно является частным случаем сложной проблемы локализации приложений. К локализации, кроме возможности использования национального алфавита, относятся, например, представление даты, времени и обозначение национальной валюты.
Коды символов определяются реализацией, в частности, возможностями операционной системы. Набор кодов для некоторого множества символов называется кодовой страницей (кодировкой).Проблема вывода русских букв в консольное окно возникла при переходе от операционной системы MS DOS к системе Windows. В консольном окне Windows по умолчанию используется кодировка, принятая в MS DOS, для того чтобы старые программы MS DOS правильно работали в консольном окне Windows. Однако среда разработки Visual Studio.NET 2005 работает в системе Windows, в которой по умолчанию установлена другая кодовая страница. Русские символы, набираемые в окне редактора среды, имеют другую кодировку, и поэтому в консольном окне видны как "иероглифы".
Есть множество способов решения этой проблемы. Самый простой - вообще отказаться от русских букв. Если же все-таки хочется их использовать, проще всего воспользоваться функцией setlocale, унаследованной из языка С (она описана в заголовочном файле <clocale>):
setlocale( LC_ALL, "Russian" );
setlocale( LC_ALL, "rus" );
Любой из этих вызовов устанавливает русскую локаль,после чего русские константы выводятся в консольное окно по-русски при использовании и printf, и cout.
Чтобы русификация консольного окна работала, необходимо, чтобы в операционной системе Windows в настройках языков и стандартов была установлена кириллица по умолчанию.
Выражения
В любой программе требуется производить вычисления. Для вычисления значений используются выражения, которые состоят из операндов, знаков операций и скобок. В приведенных выше примерах программ выражения использовались для вычисления суммы в рублях. Другие примеры выражений:
( a + 0.12 ) / 6
x && y || ! z
( t * sin( x ) - 1.05e4 ) / ( ( 2 * k + 2 ) * (2 * k + 3 ) )
a = b = c
b++
cout << a
i++, j++
Операнды задают данные для вычислений. Операции задают действия, которые необходимо выполнить. Каждый операнд является, в свою очередь, выражением или одним из его частных случаев, например, константой или переменной. Операции выполняются в соответствии с приоритетами. Для изменения порядка выполнения операций используются круглые скобки. Уровень их вложенности не ограничен.
Язык С++ предоставляет в наше распоряжение внушительный набор операций: арифметические, логические, поразрядные, операции отношения, выделения памяти, преобразования типа, выбора и т. д. В таблице 2.1 приведены простейшие операции, с которых мы начнем изучение.
Таблица 2.1. Простейшие операции языка С++ |
|
Операция |
Краткое описание |
Унарные операции |
|
++ |
постфиксный инкремент |
-- |
постфиксный декремент |
sizeof |
размер объекта или типа |
-- |
префиксный декремент |
++ |
префиксный инкремент |
! |
логическое отрицание |
- |
арифметическое отрицание (унарный минус) |
+ |
унарный плюс |
(<тип>) |
преобразование типа |
Бинарные и тернарная операции |
|
* |
умножение |
/ |
деление |
% |
остаток от деления |
+ |
сложение |
- |
вычитание |
< |
меньше |
<= |
меньше или равно |
> |
больше |
>= |
больше или равно |
== |
равно |
!= |
не равно |
&& |
логическое И |
|| |
логическое ИЛИ |
? : |
условная операция (тернарная) |
= |
присваивание |
*= |
умножение с присваиванием |
/= |
деление с присваиванием |
%= |
остаток отделения с присваиванием |
+= |
сложение с присваиванием |
-= |
вычитание с присваиванием |
, |
последовательное вычисление |
Операции расположены в порядке убывания приоритета, операции с разными приоритетами отделены горизонтальной чертой. Уровней приоритетов в языке С++ огорчительно много, поэтому в случае сомнений надо не лениться обращаться к справочной информации. Основные правила, тем не менее, просты и соответствуют принятым в математике: например, вычитание имеет более низкий приоритет, чем умножение, поэтому для того, чтобы оно было выполнено раньше, соответствующая часть выражения заключается в скобки.
Если в одном выражении записано несколько операций одинакового приоритета, то унарные операции, условная операция и операции присваивания выполняются справа налево, остальные - слева направо. Например, a = b = c означает a = (b = c), а a + b + c означает (a + b) + c.
Порядок вычисления операндов в выражении не определен: например, нельзя считать, что в выражении (sin(x + 2) + cos(y + 1)) обращение к синусу будет выполнено раньше, чем к косинусу. Только четыре операции гарантируют порядок вычислений слева направо: ,, ?:, && и ||.
Результат вычисления выражения характеризуется значением и типом. Например, пусть описаны две переменные целого типа a и b:
int a = 2, b = 5;
Тогда выражение a + b имеет значение 7 и тип int. В С++ различаются так называемые L-значения (L-value) и R-значения (R-value). Название произошло от операции присваивания:
Выражение, являющееся L -значением (от слова Left - левый), может располагаться как с левой, так и с правой стороны операции присваивания;
Выражение, являющееся R -значением (от слова Right - правый), может располагаться только с правой, но никак не с левой стороны операции присваивания.
Выражения возвращают в качестве результата либо L -значения, либо R -значения. Переменная - частный случай L -значения, а константа - частный случай R -значения. Более общим случаем R -значения является обычное арифметическое выражение. L -значением в общем случае может быть не только переменная, но и некоторое выражение, ссылающееся на область памяти. В дальнейшем мы будем указывать, какие операции возвращают L -значение.
Рассмотрим подробнее некоторые операции.
Операции присваивания ( =, +=, -=, *= и т. д.). Формат операции простого присваивания ( = ):
операнд_1 = операнд_2
Левым операндом должно быть L -значение, а правым - любое выражение. Сначала вычисляется выражение, стоящее в правой части операции, а потом его результат записывается в область памяти, ссылка на которую стоит в левой части (мнемоническое правило: "присваивание - это передача данных "налево""). В простейшем и наиболее распространенном случае левый операнд представляет собой переменную, куда и записывается вычисленное значение. То, что ранее хранилось в этой переменной, естественно, теряется.
Если тип значения, полученного в результате вычисления, не совпадает с типом левого операнда, то выполняется преобразование типа по умолчанию (об этом - в конце этой лекции).
Выражение с операцией присваивания может участвовать в качестве операнда в других выражениях. Например, оно может быть аргументом операции сложения.
Результат выражения с присваиванием является L -значением, поэтому выражение с присваиванием может быть аргументом другой операции присваивания. Таким образом, допустимы многократные присваивания вида a = b = c: сначала вычисляется выражение b = c, а затем его результат становится правым операндом для операции присваивания переменной a.
Выражения с операциями присваивания могут использоваться и как самостоятельные операторы. Для этого нужно после выражения поставить точку с запятой. Пример операции присваивания:
#include <iostream>
using namespace std;
int main()
{ int a = 3, b = 5, с = 7; // инициализация
a = b; b = a; с = с + 1; // присваивание
cout << "a = " << a
<< "\t b = " << b
<< "\t c = " << c;
с = a + ( b = 5 );
cout << "\t c = " << c;
}
Результат работы программы:
a = 5 b = 5 c = 8 с = 10
В составных операциях присваивания ( +=, *=, /= и т. п.) при вычислении выражения, стоящего в правой части, используется и L -значение из левой части. Например, при сложении с присваиванием к значению левого операнда прибавляется значение правого, и результат записывается в левый операнд. Таким образом, выражение a += b является более компактной записью выражения a = a + b.
Операции увеличения и уменьшения на 1 ( ++ и -- ). Эти операции, называемые также инкрементом и декрементом, имеют две формы записи - префиксную, когда операция записывается перед операндом, и постфиксную. В префиксной форме сначала изменяется операнд, и новое значение является результатом операции. В постфиксной форме значением выражения является исходное значение операнда, после чего он изменяется:
#include <cstdio>
using namespace std;
int main()
{ int x = 3, y = 3;
printf( "Значение префиксного выражения: %d \n", ++x );
printf( "Значение постфиксного выражения: %d \n", y++ );
printf( "Значение х после приращения: %d \n", x );
printf( "Значение у после приращения: %d \n", у );
}
Результат работы программы:
Значение префиксного выражения: 4
Значение постфиксного выражения: 3
Значение х после приращения: 4
Значение у после приращения: 4
Как и выражения с присваиванием, выражения с инкрементом и декрементом можно сделать самостоятельным оператором, задав после выражения точку с запятой.
Операции отрицания ( -,!). Арифметическое отрицание (унарный минус -) изменяет знак операнда целого или вещественного типа на противоположный. Логическое отрицание ( !) дает в результате значение false, если операнд есть true, и значение true, если операнд равен false. Операнд может быть арифметического типа. В этом случае выполняется неявное преобразование в тип bool.
Деление ( / ) и остаток от деления ( % ). Операция деления применима к операндам арифметического типа. Если оба операнда целочисленные, результатом операции является целая часть частного (дробная часть отсекается). Например, результатом 5/2 будет 2. Если же хотя бы один операнд вещественный, то и результат будет вещественным числом. В этом случае тип результата определяется правилами преобразования типов, которые рассмотрены в следующем разделе. Операция остатка от деления применяется только к целочисленным операндам. Знак результата зависит от реализации.
#include <cstdio>
using namespace std;
int main()
{int x = 11, y = 4;
float z = 4;
printf( "Результаты деления: %d %f \n", x / y, x / z );
printf( "Остаток: %d \n", x % y );
}
Результат работы программы:
Результаты деления: 2 2.750000
Остаток: 3
Операции отношения (<, <=, >, >=, ==, !=) сравнивают первый операнд со вторым. Операнды могут быть арифметического типа или указателями. Результатом операции является значение true или false. Операции сравнения на равенство и неравенство имеют меньший приоритет, чем остальные операции сравнения.
Обратите внимание на разницу между операцией проверки на равенство ( == ) и операцией присваивания ( = ), результатом которой является значение, присвоенное левому операнду.
Логические операции (&& и ||). Операнды логических операций И (&&) и ИЛИ (||) должны иметь тип, допускающий преобразование к типу bool, при этом операнды в одной операции могут быть различных типов. Результатом операции является true или false. Результат операции логическое И имеет значение true только если оба операнда имеют значение true. Результат операции логическое ИЛИ имеет значение true, если хотя бы один из операндов имеет значение true. Логические операции выполняются слева направо. Если значения первого операнда достаточно, чтобы определить результат операции, второй операнд не вычисляется.
Условная операция ( ?:).Эта единственная в С++ тернарная операция (имеет три операнда), ее формат:
операнд_1 ? операнд_2 : операнд_3
Операнды вычисляются слева направо. Результат вычисления первого операнда должен быть типа, который можно преобразовать к типу bool. Если результат равен true, то результатом выполнения всей условной операции будет значение второго операнда, иначе - третьего операнда. Их типы могут быть различными.
Пример: пусть требуется, чтобы некоторая целая величина увеличивалась на 1, если ее значение не превышает n, а иначе принимала значение 1. Это можно записать с помощью одной строки кода:
i = ( i < n ) ? i + 1 : 1;
Операция последовательного вычисления "запятая" (,). Формат операции:
выражение_1, выражение_2
Операция выполняется слева направо: сначала вычисляется выражение слева от знака операции (его результат отбрасывается), а затем вычисляется выражение справа от знака и его результат принимается за результат операции. Вычисление левого выражения обязательно завершается до того, как начнется вычисление правого выражения. Это позволяет присваивать значения переменным в левом выражении, а затем использовать их в правом. Например, результатом операции j = 2, j = 1 будет 1, результатом операции j = 2, j++ будет 2, а результатом операции j = 2, ++j будет 3.
Стандарт разрешает любое выражение заменить последовательностью выражений, разделенных операцией "запятая". Результатом вычисления последовательности выражений будет значение самого правого выражения.
Операции, не рассмотренные в этом разделе, будут описаны по мере необходимости.
