Операции, выражения и операторы

Понятие выражения, как и понятие переменной, заимствовано из алгебры. Выражение - это группа символов, представляющее некоторое значение. Оно может содержать числа, символы для математических действий, такие как сложение или деление, и даже имена переменных. Например, выражение

(4 х 5) - 4 представляет значение 16.

Почленная интерпретация этого выражения - "взять число 4, умножить его на 5, из результата вычесть 4".

В языке С существует три типа выражений:

- математическое выражение, дающее численный результат;

- текстовое выражение, дающее строку символов;

- логическое выражение, дающее в результате 1 или 0 (интерпретируемые как "истина" или "ложь".

В зависимости от количества операндов различают унарные (один операнд), бинарные (два операнда) и тренарные (три операнда).

Унарные операции:

Операция Описание Пример
& Получение адреса операнда int MyVal = 1024; int *pint; pint = &MyVal; *pint = *pint + 1; cout << MyVal;
* Обращение по адресу к значению (разыменование)
- Унарный минус – изменение знака арифметического операнда Изменение знака арифметического операнда
+ Унарный плюс Введен для симметрии с унарным минусом
~ Поразрядное инвертирование внутреннего двоичного кода unsigned short i; (0 ... 65 535); i=10; i=~i; cout << i;
! Логическое отрицание значения операнда  
++ Инкремент (префиксный или постфиксный)  
-- Декремент (префиксный или постфиксный)  
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.