Опубликован: 25.08.2010 | Доступ: свободный | Студентов: 6102 / 599 | Оценка: 3.91 / 3.44 | Длительность: 11:09:00
Лекция 2:

Простейшие программы

< Лекция 1 || Лекция 2: 123 || Лекция 3 >

Рассмотрим подробнее некоторые операции.

Операции присваивания ( =, +=, -=, *= и т. д.). Формат операции простого присваивания ( = ):

операнд_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.

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

Операции, не рассмотренные в этом разделе, будут описаны по мере необходимости.

Преобразования базовых типов

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

( char, short ) -> int -> unsigned int -> 
		  long -> unsigned long -> float -> 
		  double -> long double

Это не означает, что преобразование типа int в double выполняется последовательно по цепочке, просто менее "объемный" тип преобразуется к более "объемному". Типы char и short перед выполнением операции обязательно преобразуются к int. Типом результата выражения обычно является самый "объемный" из типов операндов.

Однако в выражениях с операцией присваивания встречается и обратный вариант, когда более "объемный" тип присваивается менее "объемному", например, float в int. Подобные преобразования связаны с потерей информации (дробная часть отбрасывается), поэтому называются сужающими приведениями (преобразованиями). Компилятор предупреждает о таких операциях.

В логических операциях и условной операции выполняется неявное преобразование к типу bool. При этом любое значение, не равное нулю (даже отрицательное), трактуется как true, а нуль считается false. При обратных преобразованиях величин типа bool к целому типу значение true преобразуется в целую константу 1, а значение false - в 0.

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

( тип ) выражение
тип ( выражение )

Результатом операции является значение заданного типа, например:

int a = 2;
float b = 6.8;
printf( "%lf %d", double ( a ), ( int ) b );

Величина a преобразуется к типу double, а переменная b - к типу int с отсечением дробной части (сужающее приведение).

Явное преобразование типа в стиле С оставлено в С++ только для совместимости. Использовать его не рекомендуется, поскольку оно слишком универсально, а потому чревато плохо диагностируемыми ошибками.

В стандарте С++ определено четыре специализированных операций преобразования типа, которые не являются взаимозаменяемыми и применяются в разных ситуациях:

static_cast<тип>( выражение )					
reinterpret_cast<тип>( выражение )			
dynamic_cast<тип>( выражение )				
const_cast<тип>( выражение )

В зависимости от вида преобразования необходимо использовать соответствующую ему операцию приведения типа. Приведение типа static_cast<T>(e) используется между родственными типами. Его может проверить компилятор. Операция reinterpret_cast выполняет преобразование типов без проверки при компиляции. Оно часто необходимо тогда, когда точно известно, что объекты разных типов занимают в памяти одинаковое количество байт и фактического преобразования делать как раз не нужно. Операция const_cast аннулирует действие модификатора const и применяется достаточно редко. Операция dynamic_cast выполняет преобразование во время работы программы и применяется для преобразования указателей и ссылок родственных полиморфных классов. Примеры применения этих операций вы увидите в следующих лекциях.

< Лекция 1 || Лекция 2: 123 || Лекция 3 >
Dana Kanatkyzi
Dana Kanatkyzi
Здравствуйте.Помогите решить задачу минимум 4 чисел.Условие такое:"Напишите функцию int min (int a, int b, int c, int d) (C/C++)"находящую наименьшее из четырех данных чисел."Заранее спасибо!
Юрий Семевский
Юрий Семевский
Россия, Санкт-Петербург
Александр Богдашов
Александр Богдашов
Россия