Приоритет логических операций c. Приоритеты операций

Приоритет операций.

Всем наверно с детства знакома задачка с подковыркой, когда опоненту говорят сколько будет два плюс два умножить на два. Многие забывают что в математике сначала надо умножать, а потом только прибавлять, и потому ответ не 8, а 6.

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

Операции в скобках

Функции (типа sqrt, cos и другие)

Умножение, деление, остаток от деления (слева направо, как в обычной жизни)

Сложение вычитание (слева направо, как в обычной жизни)

Для примера рассмотрим следующее выражение записанное на языке Си:

Приоритет арифметических операций

Над каждым действием вы видите каким оно выполняется по счету.

Для изменения порядка выполнения операций используются круглые скобки. Например, если записать:

Листинг 4.10

Компьютер сначала поделит а на b, и потом умножит полученный результат на с. Но, если нам надо посчитать чему равно a деленное на произведение b*c, тогда нужно использовать скобки.

Листинг 4.11

15. Элементарный ввод-вывод в языке Си.

Функция форматного вывода printf()

printf(форматная_строка, список_вывода)

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

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

произвольный текст (обычно он поясняет значения выводимых переменных); среди символов этого текста могут быть и управляющие; в несложных программах этого пособия часто будет использоваться управляющий символ "\n" ;

спецификации форматов, показывающие, в каком виде должны выводиться значения переменных; каждая спецификация соответствует одной переменной; спецификации встречаются в форматной строке в том порядке, в каком перечисляются выводимые переменные в списке вывода; каждая спецификация начинается с символа %; спецификация стоит в том месте текста, где должно выводиться значение соответствующей переменной.

Спецификация формата вывода или ввода

В простейшем виде спецификация формата имеет вид:

%ширина_поля.точность спецификатор

Ширина поля - положительное целое число, задающее минимальное количество позиций, занимаемых выводимым значением; если число символов в выводимом значении меньше, чем ширина поля, то выводимое значение дополняется пробелами до минимальной длины; если число символов в выводимом значении больше ширины поля или ширина поля не задана, то печатаются все символы значения (ширина поля игнорируется).

Точность - положительное целое число, указывается в основном для вещественных чисел, означая в этом случае количество выводимых после десятичной точки цифр.

На первых этапах обучения программированию достаточно следующих спецификаторов:

d - для целых значений (типов int, char, unsigned);

f - для вещественных значений (типов float, double);

e - для вещественных значений (типов float, double)с указанием порядка, т. е. в виде:

Другие примеры оператора printf() представлены на рис.1.

Функция форматного ввода scanf()

Оператор вызова этой функции имеет вид:

scanf(форматная_строка, список_ввода)

Список ввода показывает, что выводить. Он содержит перечисленные через запятую адреса вводимых переменных. Почему адреса, а не имена переменных станет понятно после знакомства с функциями Си (часть I I пособия). Записать адрес переменной нетрудно, используя операцию & (см. таблицу 3). В список ввода не могут входить выражения или константы, так как ввод предполагает изменение значения.

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

Пример функции scanf:

printf("Введите i и a\n"); /* вывод приглашения к вводу */

scanf("%d%f", &i, &a);...

Форма ввода:

Введите i и a

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

Заметим также, что при вводе строк символов с помощью функции scanf() действуют более сложные правила. Так, в буфер устройства ввода считываются все символы до нажатия Enter, а в вводимую строковую переменную передаются символы до первого пробела. Такой принцип работы scanf() имеет свои преимущества, но они слишком трудны при начальном освоении языка Си. Поэтому для ввода и вывода строк лучше пользоваться функциями gets() и puts().

C++ для начинающих

4.13. Приоритеты

Приоритеты операций задают последовательность вычислений в сложном выражении. Например, какое значение получит ival?

Int ival = 6 + 3 * 4 / 2 + 2;

Если вычислять операции слева направо, получится 20. Среди других возможных результатов будут 9, 14 и 36. Правильный ответ: 14.
В С++ умножение и деление имеют более высокий приоритет, чем сложение, поэтому они будут вычислены раньше. Их собственные приоритеты равны, поэтому умножение и деление будут вычисляться слева направо. Таким образом, порядок вычисления данного выражения таков:

1. 3 * 4 => 12 2. 12 / 2 => 6 3. 6 + 6 => 12 4. 12 + 2 => 14

Следующая конструкция ведет себя не так, как можно было бы ожидать. Приоритет операции присваивания меньше, чем операции сравнения:

While (ch = nextChar() != "\n")

Программист хотел присвоить переменной ch значение, а затем проверить, равно ли оно символу новой строки. Однако на самом деле выражение сначала сравнивает значение, полученное от nextChar(), с "\n", и результат – true или false – присваивает переменной ch.
Приоритеты операций можно изменить с помощью скобок. Выражения в скобках вычисляются в первую очередь. Например:

4 * 5 + 7 * 2 ==> 34 4 * (5 + 7 * 2) ==> 76 4 * ((5 + 7) * 2) ==> 96

Вот как с помощью скобок исправить поведение предыдущего примера:

While ((ch = nextChar()) != "\n")

Операторы обладают и приоритетом , и ассоциативностью . Оператор присваивания правоассоциативен, поэтому вычисляется справа налево:

Ival = jval = kva1 = lval

Сначала kval получает значение lval, затем jval – значение результата этого присваивания, и в конце концов ival получает значение jval.
Арифметические операции, наоборот, левоассоциативны. Следовательно, в выражении

Ival + jval + kva1 + 1va1

сначала складываются ival и jval, потом к результату прибавляется kval, а затем и lval.
В таблице 4.4 приведен полный список операторов С++ в порядке уменьшения их приоритета. Операторы внутри одной секции таблицы имеют равные приоритеты. Все операторы некоторой секции имеют более высокий приоритет, чем операторы из секций, следующих за ней. Так, операции умножения и деления имеют одинаковый приоритет, и он выше приоритета любой из операций сравнения.

Упражнение 4.18

Каков порядок вычисления следующих выражений? При ответе используйте таблицу 4.4.

(a) ! ptr == ptr->next (b) ~ uc ^ 0377 & ui << 4 (c) ch = buf[ bp++ ] != "\n"

Упражнение 4.19

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

Упражнение 4.20

Следующие выражения вызывают ошибку компиляции из-за неправильно понятого приоритета операций. Объясните, как их исправить, используя таблицу 4.4.

(a) int i = doSomething(), 0; (b) cout << ival % 2 ? "odd" : "even";

Таблица 4.4. Приоритеты операций

Оператор Значение Использование
:: Глобальная область видимости ::name
:: Область видимости класса class::name
:: Область видимости пространства имен namespace::name
. Доступ к члену object.member
-> Доступ к члену по указателю pointer->member
Взятие индекса variable
() Вызов функции name(expr_list)
() Построение значения type(expr_list)
++ постфиксный инкремент lvalue++
постфиксный декремент lvalue--
typeid идентификатор типа typeid(type)
typeid идентификатор типа выражения typeid(expr)
преобразование типа const_cast(expr)
преобразование типа dynamic_cast(expr)
reinterpret_cast приведение типа reinterpret_cast (expr)
static_cast приведение типа static_cast(expr)
sizeof размер объекта sizeof expr
sizeof размер типа sizeof(type)
++ префиксный инкремент ++lvalue
-- префиксный декремент --lvalue
~ побитовое НЕ ~expr
! логическое НЕ !expr
- унарный минус -expr
+ унарный плюс +expr
* разыменование *expr
& адрес &expr
() приведение типа (type)expr
new выделение памяти new type
new выделение памяти и инициализация new type(exprlist)
new Выделение памяти под массив все формы
delete освобождение памяти все формы
delete освобождение памяти из-под массива все формы
->* доступ к члену классу по указателю pointer-> *pointer_to_member
.* доступ к члену класса по указателю object.*pointer_to_member
* Умножение expr * expr
/ Деление expr / expr
% деление по модулю expr % expr
+ сложение expr + expr
- вычитание expr - expr
<< сдвиг влево expr << expr
>> сдвиг вправо expr >> expr
< меньше expr < expr
<= меньше или равно expr <= expr
> больше expr > expr
>= больше или равно expr >= expr
== равно expr == expr
!= не равно expr != expr
& побитовое И expr & expr
^ побитовое ИСКЛЮЧАЮЩЕЕ ИЛИ expr ^ expr
| побитовое ИЛИ expr | expr
&& логическое И expr && expr
|| логическое ИЛИ expr || expr
?: условный оператор expr ? expr * expr
= присваивание l-значение = expr
=, *=, /=, %=, +=, -=, <<=, >>=, &=, |=, ^= составное присваивание l-значение += expr и т.д.
throw возбуждение исключения throw expr
, запятая expr, expr

Приоритет и порядок выполнения

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

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

Таблица 4.1.

Приоритет и ассоциативность операций в языке Си

Знак операции Наименование Ассоциативность
() . -> Первичные Слева направо
+ - ~ ! * & ++ -- sizeof приведение типа Унарные Справа налево
* / % Мультипликативные Слева направо
+ - Аддитивные Слева направо
>> << Сдвиг Слева направо
< > <= >= Отношение Слева направо
== != Отношение Слева направо
& Поразрядное И Слева направо
^ Поразрядное исключающее ИЛИ Слева направо
| Поразрядное включающее ИЛИ Слева направо
&& Логическое И Слева направо
|| Логическое ИЛИ Слева направо
?: Условная Справа налево
= *= /= %= += -= <<= >>= &= |= ^= Простое и составное присваивание Справа налево
, Последовательное вычисление Слева направо

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

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

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

а = b & 0xFF + 5

вычисляется как

а = b & (0xFF + 5),

а выражение

а +с >> 1

вычисляется как

(а + с) >> 1

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

В СП ТС реализована операция унарного плюса, позволяющая гарантировать порядок вычисления выражений в скобках.

Операция последовательного вычисления, логические операции И и ИЛИ, условная операция и операция вызова функции гарантируют определенный порядок вычисления своих операндов. Операция последовательного вычисления обеспечивает вычисление своих операндов по очереди, слева направо (запятая, разделяющая аргументы в вызове функции, не является операцией последовательного вычисления и не обеспечивает таких гарантий). Гарантируется лишь то, что к моменту вызова функции все аргументы уже вычислены.

Условная операция вычисляет сначала свой первый операнд, а затем, в зависимости от его значения, либо второй, либо третий.

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

int х, у, z, f();

z = х > у || f(x, у);

Сначала вычисляется выражение х>у. Если оно истинно, то переменной z присваивается значение 1, а функция f не вызывается. Если же значение х не больше у, то вычисляется выражение f(x,y). Если функция f возвращает ненулевое значение, то переменной z присваивается 1, иначе 0. Отметим также, что при вызове функции f гарантируется, что значение ее первого аргумента больше второго.

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

if(!feof(pf)) && (с = getc(pf)) …

Здесь feof - функция проверки на конец файла, getc - функция чтения символа из файла (см. раздел 12).

В-третьих, можно гарантировать, что в выражении f(x)&&g(y) функция f будет вызвана раньше, чем функция g . Для выражения f(x)+g(y) этого утверждать нельзя.

В последующих примерах показано группирование операндов для различных выражений.

Выражение Группирование операндов
a & b || c (a & b) || c
a = b || c a = (b || c)
q && r || s-- (q && r) || (s--)
p == 0 ? p += 1: p += 2 (p == 0 ? p += 1: p) += 2

В первом примере поразрядная операция И (&) имеет больший приоритет, чем -логическая операция ИЛИ (||), поэтому выражение а&b является первым операндом логической операции ИЛИ.

Во втором примере логическая операция ИЛИ (||) имеет больший приоритет, чем операция простого присваивания, поэтому выражение b||с образует правый операнд операции присваивания. (Обратите внимание на то, что значение, присваиваемое а , есть нуль или единица.)

Чтобы правильно вычислять выражения (например, 4 + 2 * 3), мы должны знать, какие операторы что значат и в каком порядке их следует применять. Эта последовательность, в которой они выполняются, называется приоритетом операций . Следуя обычным правилам математики (в которой умножение следует выполнять перед сложением), выражение выше решается так — 4 + (2 * 3), результат — значение 10.

В C++ все операторы (операции) имеют свой уровень приоритета. Те, в которых он выше – выполняются первыми. В таблице ниже можно видеть, что приоритет операций умножения и деления (5) выше, чем в операциях сложения и вычитания (6). Компилятор использует это для определения порядка обработки выражений.

А что делать, если у двух операторов в выражении одинаковый уровень приоритета и они размещены рядом? Какую операцию выполнять первой? А здесь уже компилятор будет пользоваться правилами ассоциативности, которые указывают направление выполнения операций: слева направо или справа налево. Например, в 3 * 4 / 2, операции умножения и деления имеют одинаковый уровень приоритета — 5. А ассоциативность 5 уровня — слева направо, так что решать будем так: (3 * 4) / 2 = 6.

Таблица приоритета операций

Примечания :

1 – это самый высокий уровень приоритета, а 17 – самый низкий. Операции с более высоким уровнем приоритета выполняются первыми.

L -> R означает слева направо.

R -> L означает справа налево.

Ассоциативность Оператор Описание Пример
1. Нет :: Глобальная область видимости (унарный) ::name
:: Область видимости класса (бинарный) class_name::member_name
2. L->R () Круглые скобки (expression)
() Вызов функции function_name(parameters)
() Инициализация type name(expression)
{} Uniform инициализация (C++11) type name{expression}
type() Functional cast new_type(expression)
type{} Functional cast (C++11) new_type{expression}
Индекс массива pointer
. Доступ к члену объекта object.member_name
-> Доступ к члену объекта через указатель object_pointer->member_name
++ Пост-инкремент lvalue++
–– Пост-декремент lvalue––
typeid Информация о типе во время выполнения typeid(type) or typeid(expression)
const_cast Cast away const const_cast(expression)
dynamic_cast Run-time type-checked cast dynamic_cast(expression)
reinterpret_cast Cast one type to another reinterpret_cast(expression)
static_cast Compile-time type-checked cast static_cast(expression)
3. R->L + Унарный плюс +expression
Унарный минус -expression
++ Пре-инкремент ++lvalue
–– Пре-декремент ––lvalue
! Логическое НЕ (NOT) !expression
~ Побитовое НЕ (NOT) ~expression
(type) C-style cast (new_type)expression
sizeof Размер в байтах sizeof(type) or sizeof(expression)
& Адрес &lvalue
* Dereference *expression
new Динамическое выделение памяти new type
new Динамическое распределение массива new type
delete Динамическое удаление памяти delete pointer
delete Динамическое удаление массива delete pointer
4. L->R ->* Member pointer selector object_pointer->*pointer_to_member
.* Member object selector object.*pointer_to_member
5. L->R * Умножение expression * expression
/ Деление expression / expression
% Остаток expression % expression
6. L->R + Сложение expression + expression
Вычитание expression — expression
7. L->R << Побитовый сдвиг влево expression << expression
>> Побитовый сдвиг вправо expression >> expression
8. L->R < Сравнение. Меньше чем expression < expression
<= Сравнение. Меньше чем или равно expression <= expression
> Сравнение. Больше чем expression > expression
>= Сравнение. Больше чем или равно expression >= expression
9. L->R == Равно expression == expression
!= Не равно expression != expression
10. L->R & Побитовое И (AND) expression & expression
11. L->R ^ Побитовое исключающее ИЛИ (XOR) expression ^ expression
12. L->R | Побитовое ИЛИ (OR) expression | expression
13. L->R && Логическое И (AND) expression && expression
14. L->R || Логическое ИЛИ (OR) expression || expression
15. R->L ?: Тернарный условный оператор (см. примечание ниже) expression ? expression: expression
= Присваивание lvalue = expression
*= Умножение с присваиванием lvalue *= expression
/= Деление с присваиванием lvalue /= expression
%= Деление с остатком с присваиванием lvalue %= expression
+= Сложение с присваиванием lvalue += expression
-= Вычитание с присваиванием lvalue -= expression
<<= Присваивание с побитовым сдвигом влево lvalue <<= expression
>>= Присваивание с побитовым сдвигом вправо lvalue >>= expression
&= Присваивание с побитовой операцией И (AND) lvalue &= expression
|= Присваивание с побитовой операцией ИЛИ (OR) lvalue |= expression
^= Присваивание с побитовой операцией «исключающее ИЛИ» (XOR) lvalue ^= expression
16. R->L throw Создание исключения вручную throw expression
17. L->R , Оператор Comma (запятая) expression, expression

Примечание : Выражение в середине условного оператора?: выполняется как если бы оно находилось в круглых скобках.

Некоторые операторы вы уже знаете: +, -, *, /, (), =, <,>, <= и >=. Их значения одинаковы как в математике, так и в C++.

Однако, если у вас нет опыта работы с другими языками программирования, то большинство этих операторов вам сейчас непонятны. Это нормально. Мы рассмотрим большую часть из них в этой главе, а об остальных расскажем по мере необходимости.

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

Как возводить в степень в C++?

Вы уже должны были заметить, что оператор ^, который обычно используется для обозначения возведения в степень в обычной математике, не является таковым в C++. В С++ это побитовая операция XOR. Так что же тогда вместо ^? А вместо этого – функция pow(), которая находится в заголовочном файле :

#include double x = pow(3.0, 4.0); // 3 в степени 4

#include

double x = pow (3.0 , 4.0 ) ; // 3 в степени 4

Обратите внимание, параметры и возвращаемые значения функции pow() — типа double. А поскольку типы с плавающей точкой известны ошибками округления, то результаты pow() могут быть слегка неточными (чуть меньше или чуть больше).

Если вам нужно возвести в степень целое число, то лучше использовать собственную функцию, например:

// примечание: экспонент не должен быть отрицательным int pow(int base, int exp) { int result = 1; while (exp) { if (exp & 1) result *= base; exp >>= 1; base *= base; } return result; }

// примечание: экспонент не должен быть отрицательным

int pow (int base , int exp )

int result = 1 ;

while (exp )

if (exp & 1 )

result * = base ;

exp >> = 1 ;

base * = base ;

return result ;

Здесь используется алгоритм «Возведения в степень путем возведения в квадрат».

Не переживайте, если что-то не понятно. Просто помните о проблеме переполнения, которое может произойти, если один из аргументов будет слишком большим.

Тест

1) Из школьной математики вы знаете, что выражения внутри скобок выполняются первыми. Например, в (2 + 3) * 4 , часть (2 + 3) будет выполнятся первой.

В этом задании есть 4 выражения, в которых отсутствуют какие-либо скобки. Используя приоритет операций и правила ассоциативности в таблице выше, добавьте скобки в каждое выражение так, как если бы их обрабатывал компилятор.

Подсказка : Используйте колонку Пример в таблице выше, чтобы определить, является ли оператор унарным (имеет один операнд) или бинарным (два операнда). Если забыли, что такое унарный или бинарный — смотрите урок 17 .

Пример решения: х = 2 + 3 % 4

Бинарный оператор % имеет более высокий приоритет, чем оператор + или =, поэтому он применяется первым: х = 2 + (3 % 4);

Бинарный оператор + имеет более высокий приоритет, чем =, поэтому следующим применяется он.

Задания

а) x = 3 + 4 + 5;
б) x = y = z;
в) z *= ++y + 5;
г) a || b && c || d;

Ответ

а) Уровень приоритета бинарного оператора + выше, чем в =:

х = (3 + 4 + 5);

Ассоциативность бинарного оператора + слева направо:

Ответ: х = ((3 + 4) + 5).

б) Ассоциативность бинарного оператора = справа налево:

Ответ: x = (y = z).

в) Унарный оператор ++ имеет наивысший приоритет:

Бинарный оператор + имеет второй наивысший приоритет:

Ответ: z *= ((++y) + 5).

г) Бинарный оператор && имеет более высокий приоритет, чем ||:

a || (b && c) || d;

Ассоциативность бинарного оператора || слева направо:

Ответ: (a || (b && c)) || d.

Порядок выполнения операций при вычислении значения выражения определяется расположением знаков операций , круглых скобок и приоритетом операций . Операции с наивысшим приоритетом выполняются в первую очередь. Если в выражении содержится несколько операций одного приоритета на одном и том же уровне, то их обработка производится в соответствии с порядком выполнения – справа налево или слева направо. Если необходимо изменить порядок выполнения операций в выражении, то следует использовать круглые скобки, например (x + y) * z.

Приоритет операции запятая ниже, чем у всех остальных операций.

В приведенной ниже таблице операции языка C++ приведены в порядке убывания приоритета. Операции с разными приоритетами разделены чертой.

Таблица приоритетов операций

Знаки операций

Названия операций

Порядок выполнения

повышение приоритета

постфиксный инкремент

постфиксный декремент

слева направо

sizeof

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

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

размер операнда в байтах

префиксный инкремент

префиксный декремент

поразрядное Н Е

логическое НЕ

унарные минус, плюс

преобразование типа

справа налево

умножение

остаток от деления целых

слева направо

сложение

вычитание

слева направо

сдвиг влево

сдвиг вправо

слева направо

меньше или равно

больше или равно

слева направо

слева направо

поразрядное И

слева направо

поразрядное исключающее ИЛИ

слева направо

поразрядное ИЛИ

слева направо

логическое И

слева направо

логическое ИЛИ

слева направо

? :

условная

справа налево

*= , /= , %=

+= , - =

<<= , >>=

&= , |= , ^=

присваивание (простое и

составное)

справа налево

операция запятая

слева направо

Приведение (преобразование) типа

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

Автоматически производятся лишь преобразования, которые преобразуют операнды с меньшим диапазоном значений в операнды с большим диапазоном значений, поскольку это происходит без какой-либо потери информации. Например, если в выражении ival + f v al переменная ival типа int , а переменная f v al – типа float , то при выполнении операции (+ ) значение переменной iv al будет приведено к типу float .

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

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

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

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

Операндом операции приведения типа является преобразуемое выражение. Приоритет операции приведения типа такой же, как и у других унарных операций. Например: (long double ) 5; (int ) f; (double) a/2.

Если рассматриваемое выражение имеет достаточно сложный вид, желательно брать его в скобки, чтобы убедится, что тип будет изменен у результата всего выражения, а не у его части. Например,

(int ) x + b * c

(int ) (x + b * c )

В первом случае преобразование относится к переменной x , во втором – ко всему выражению x + b * c .