
- •1. Порядок выполнения работы
- •2. Предмашинная подготовка задачи
- •2.1. Алфавит
- •2.2. Простейшие конструкции
- •2.2.1. Ключевые слова
- •2.2.2. Переменные
- •2.2.4. Вызов функций
- •2.3. Выражения
- •2.3.1. Арифметические операции
- •2.4. Операторы
- •2.5.1. Комментарии
- •2.5.2. Директивы препроцессора
- •2.5.3. Глобальные переменные
- •2.5.4. Тело программы.
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) недопустима.