Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Концепция решения информационных задач.doc
Скачиваний:
1
Добавлен:
01.03.2025
Размер:
583.68 Кб
Скачать

2.3.1. Арифметические операции

Арифметические операции служат для описания арифметических действий: замена знака (-), инкремент (++), декремент (--), сложение (+), вычитание (-), умножение (*), деление (/), а также вычисление остатка от деления (%). Операторы замены знака, инкремента и декремента – однооперандные (унарные), а их использование приводит соответственно к смене знака операнда, добавлению к операнду числа 1 и вычитанию из операнда числа 1. Если операнд операции замены знака имеет тип unsigned, то замена знака реализуется путём вычитания операнда из числа 2n , где n – число битов, используемых для представления данных типа int.

Как и в Ассемблере, в С++ имеется эффективное средство увеличения и уменьшения значения операнда на единицу – унарные операции инкремента и декремента.

Унарные операции инкремента/декремента преобразуются компилятором в машинных код однозначно и на языке Ассемблера могут выглядеть так:

инкремент: INC N

декремент: DEC N

где N может быть либо регистром процессора, либо содержимым ячейки памяти.

По отношению к операнду данный вид операций может быть префиксным и постфиксным. Префиксная операция применяется к операнду перед использованием полученного результата. Постфиксная операция применяется к операнду после использования операнда.

Понятие префикса или постфикса имеет смысл главным образом в выражениях с присваиванием:

x = y++; // постфикс

index = --current;//префикс

count++; //унарная операция

//то же, что ++count;

abc--; //то же, что --abc;

Здесь переменная у сначала присваивается переменной х, а затем увеличивается на единицу. Переменная current сначала уменьшается на единицу, после чего результат присваивается переменной index.

Операция взятия остатка применяется только к целочисленным операндам (char, short, int, long) и дает остаток от деления первого операнда на второй. Например, результатом операции 6%2 будет 0, 5%2 будет 1, 7%4 будет 3 и т.д. Знак результата операции совпадает со знаком делимого.

Специальной операции деления нацело в С/С++ нет — для него применяется обычная операция деления (/). Если оба операнда ее являются целыми, то результат этой операции также будет целым, равным частному от деления с остатком первого операнда на второй.

Внимание! В качестве предостережения заметим, что это свойство деления в С часто бывает источником ошибок даже у довольно опытных программистов. Предположим, некто хочет вычислить объем шара и пишет, переводя известную формулу на язык С:

volume = 4/3*Pi*r*r*r;

Все операции в выражении правой части имеют одинаковый приоритет, и оценка выражения производится в последовательности слева направо. На первом шаге производится деление 4/3, но это будет делением нацело с результатом, равным 1. Эта единица преобразуется далее в вещественное 1.0. Коэффициент в формуле, таким образом, получается равным 1.0 вместо ожидаемого 1.333...

Смешанные выражения

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

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

сhar, short

int, long

float

double

long double

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

Операция преобразования типа

Операция преобразования типа – однооперандная и в общем случае имеет вид

имя_типа(выражение) или (имя_типа)выражение

Первая форма вызова операции называется функциональной, вторая – канонической (она унаследована от языка С). Функциональная форма применима лишь в случаях, когда тип имеет простое (в одно слово) наименование. Результатом преобразования в обоих случаях является значение выражения-операнда, преобразованное к заданному типу. Например:

int i = 1;

float f = float(i+1);

unsigned long ul = (unsigned long)i;

В последней строке функциональная форма unsigned long(i) недопустима.