Операции, выражения и операторы
Понятие выражения, как и понятие переменной, заимствовано из алгебры. Выражение — это группа символов, представляющее некоторое значение. Оно может содержать числа, символы для математических действий, такие как сложение или деление, и даже имена переменных. Например, выражение
(4 х 5) — 4 представляет значение 16.
Почленная интерпретация этого выражения — взять число 4, умножить его на 5, из результата вычесть 4.
В языке С существует три типа выражений:
— математическое выражение, дающее численный результат;
— текстовое выражение, дающее строку символов;
— логическое выражение, дающее в результате 1 или 0 (интерпретируемые как истина или ложь.
В зависимости от количества операндов различают унарные (один операнд), бинарные (два операнда) и тренарные (три операнда).
Унарные операции:
Операция | Описание | Пример |
Получение адреса операнда | int MyVal = 1024;int *pint;pint = &MyVal;*pint = *pint + 1;cout | |
* | Обращение по адресу к значению (разыменование) | |
— | Унарный минус – изменение знака арифметического операнда | Изменение знака арифметического операнда |
+ | Унарный плюс | Введен для симметрии с унарным минусом |
~ | Поразрядное инвертирование внутреннего двоичного кода | unsigned short i; (0 … 65 535);i=10; i=~i;cout |
! | Логическое отрицание значения операнда | |
++ | Инкремент (префиксный или постфиксный) | |
— | Декремент (префиксный или постфиксный) | |
sizeof | Вычисление размера в байтах | |
:: | Операция доступа |
Бинарные операции:
Операция | Описание операции |
Арифметические операции | |
+ | Сложение |
— | Вычитание |
* | Умножение |
/ | Деление |
% | Получение остатка от деления целочисленных операндов |
Операции отношения (сравнения) | |
Меньше | |
Больше | |
Меньше или равно | |
= | Больше или равно |
= = | Равно |
!= | Не равно |
Логические бинарные операции | |
Конъюнкция (И) | |
| | | Дизъюнкция (ИЛИ) |
Операции присваивания | |
= | Простое присваивание |
*= | Присваивание произведения значений операндов |
/= | Присваивание частного от деления значений операндов |
%= | Присваивание остатка от деления значений операндов |
+= | Присваивание суммы значений операндов |
-= | Присваивание разности значений операндов |
Операции сдвига | |
Левый сдвиг | |
Правый сдвиг | |
Поразрядные операции | |
Поразрядная конъюнкция битовых представлений значений целочисленных операндов | |
| | Поразрядная дизъюнкция -//- |
^ | Поразрядная исключающая дизъюнкция -//- |
Деление целых чисел дает в результате целое число. Дробная часть результата, если она есть, отбрасывается:
int MyVal1 = 21 / 6;
int MyVal2 = 21 / 7;
И MyVal1, и MyVal2 в итоге получат значение 3.
Один нюанс, который вы должны запомнить.
Float res;
res = 5/4;
Результат: res = 1.
Для того, чтобы посчитать правильно, этот фрагмент программы должен быть
Float res;
res = 5./4.;
Результат: res = 1.25.
Результат получения остатка от деления целочисленных операндов положителен, если оба операнда положительны. Если же один или оба операнда отрицательны, результат зависит от реализации, то есть машинно-зависим.
Значением операции сдвига является битовое представление левого операнда, сдвинутое влево () на количество разрядов, равное значению правого операнда.
При левом сдвиге на i разрядов первые i разрядов левого операнда теряются, последние i разрядов левого операнда заполняются нулями.
При правом сдвиге на i разрядов первые i разрядов левого операнда заполняются нулями, если левый операнд имеет беззнаковый тип или имеет неотрицательное значение, в противном случае значение определяется реализацией. Последние i разрядов левого операнда теряются.
Преобразование типов
Преобразование типов при присваивании.
Преобразование типов предназначено для ситуации, в которой переменные одного типа смешиваются с переменными другого типа. Когда возникает подобная ситуация в выражении присваивания, используется правило преобразования типов: значение операнда справа от операции присваивания преобразуется к типу операнда, стоящего слева. Это демонстрируется следующим примером:
int x;
char ch;
float f;
void func(void)
{
ch = x; /* 1 */
x = f; /* 2 */
f = ch; /* 3 */
f = x; /* 4 */
}
В строке 1 левые (старшие) биты целочисленной переменной x обрубаются, оставляя в ch младшие 8 битов. Если х содержит число между 255 и 0, то ch и хбудут иметь одинаковое значение. Иначе значение ch будет содержать только младший набор битов переменной х. В строке 2 х получает целую часть переменной f. В строке 3 f получает 8-битное целое число, хранящееся в ch, преобразованное к формату с плавающей точкой. В строке 4 f получает значение целочисленной переменной х, преобразованное к формату с плавающей точкой.
Когда происходит преобразование из переменной, занимающей большее количество байт в переменную с меньшим, то старшие биты будут потеряны.
Следует помнить два важных момента, которые могут повлиять на переносимость создаваемого кода:
1) Когда происходит преобразование из переменной, занимающей большее количество байт в переменную с меньшим, то старшие биты будут потеряны
2) Преобразование из int в float или из float в double и тому подобное не добавляет точности. Такого рода преобразования только изменяют формат представления значения.
Преобразование типов в выражениях. Когда операнды различных типов смешиваются в выражениях, то происходит преобразование к одному типу. Компилятор преобразует все операнды «вверх», к типу большего операнда. Ниже описываются правила преобразования типов.
1) Все переменные типа char и short int преобразуются к типу int. Все переменные типа float – к типу double.
2) Если один из пары операндов имеет тип long double, другой операнд также преобразуется к long double.
3) Если один из пары операндов имеет тип double, другой операнд (кроме long double) также преобразуется к типу double.
4) Если один из операндов имеет тип long, другой операнд также преобразуется к long.
5) Если один из операндов имеет тип unsigned, другой операнд также преобразуется к типу unsigned.
В результате применения этих правил преобразования каждая пара операндов будет иметь тип и результат каждой операции будет совпадать по типу с операндами. Рассмотрим преобразование типов, показанное на рисунке.
Char ch;
Int i;
Float f;
Double d;
result = (ch/i) + (f*d) – (f+i);
Cначала символ ch преобразуется к целому int, а вещественная переменная с одинарной точностью f преобразуется к типу double. Затем ch/i преобразуется к типу double, поскольку f*d имеет тип double. Конечный результат имеет тип double, поскольку оба операнда типа double.