Любое выражение языка состоит из операндов (переменных, констант и др.), соединенных знаками операций. Знак операции - это символ или группа символов, которые сообщают компилятору о необходимости выполнения определенных арифметических, логических или других действий.
Операции выполняются в строгой последовательности. Величина, определяющая преимущественное право на выполнение той или иной операции, называется приоритетом. В табл. 2 перечислены различные операции языка Си. Их приоритеты для каждой группы одинаковы (группы выделены цветом). Чем большим преимуществом пользуется соответствующая группа операций, тем выше она расположена в таблице. Порядок выполнения операций может регулироваться с помощью круглых скобок.
Таблица 2
Знак операции
Назначение операции
( )
Вызов функции
[ ]
Выделение элемента массива
.
Выделение элемента записи
->
Выделение элемента записи
!
Логическое отрицание
~
Поразрядное отрицание
-
Изменение знака
++
Увеличение на единицу
--
Уменьшение на единицу
&
Взятие адреса
*
Обращение по адресу
(тип)
Преобразование типа (т.е. (float) a)
sizeof( )
Определение размера в байтах
*
Умножение
/
Деление
%
Определение остатка от деления
+
Сложение
-
Вычитание
<<
Сдвиг влево
>>
Сдвиг вправо
<
Меньше, чем
<=
Меньше или равно
>
Больше, чем
>=
Больше или равно
= =
Равно
!=
Не равно
&
Поразрядное логическое "И"
^
Поразрядное исключающее "ИЛИ"
|
Поразрядное логическое "ИЛИ"
&&
Логическое "И"
||
Логическое "ИЛИ"
?:
Условная (тернарная) операция
=
Присваивание
+=, - =, *=, /=, %=, <<=, >>=, &=, |=, ^=
Составные операции присваивания (например, а *= b (т.е. a = a * b) и т.д.)
,
Операция запятая
Для исключения путаницы в понятиях "операция" и "оператор", отметим, что оператор - это наименьшая исполняемая единица программы. Различают операторы выражения, действие которых состоит в вычислении заданных выражений (например: a = sin(b)+c; j++;), операторы объявления, составные операторы, пустые операторы, операторы метки, цикла и т.д. Для обозначения конца оператора в языке Си используется точка с запятой. Что касается составного оператора (или блока), представляющего собой набор логически связанных операторов, помещенных между открывающей ({) и закрывающей (}) фигурными скобками ("операторными скобками"), то за ним точка с запятой не ставится. Отметим, что блок отличается от составного оператора наличием определений в теле блока.
Охарактеризуем основные операции языка Си. Сначала рассмотрим одну из них - операцию присваивания (=). Выражение вида
х = у;
присваивает переменной х значение переменной у. Операцию "=" разрешается использовать многократно в одном выражении, например:
x = y = z = 100;
Различают унарные и бинарные операции. У первых из них один операнд, а у вторых - два. Начнем их рассмотрение с операций, отнесенных к первой из следующих традиционных групп:
Арифметические операции.
Логические операции и операции отношения.
Операции с битами.
Арифметические операции задаются следующими символами (табл. 2): +, -, *, /, %. Последнюю из них нельзя применять к переменным вещественного типа. Например:
a = b + c;
x = y - z;
r = t * v;
s = k / l;
p = q % w;
Логические операции отношения задаются следующими символами (см. табл. 2): && ("И"), || ("ИЛИ"), ! ("НЕ"), >, >=, <, <= , = = (равно), != (не равно). Традиционно эти операции должны давать одно из двух значений: истину или ложь. В языке Си принято следующее правило: истина - это любое ненулевое значение; ложь - это нулевое значение. Выражения, использующие логические операции и операции отношения, возвращают 0 для ложного значения и 1 для истинного. Ниже приводится таблица истинности для логических операций.
Таблица 3
x
y
x&&y
x||y
!x
Битовые операции можно применять к переменным, имеющим типы int, char, а также их вариантам (например, long int). Их нельзя применять к переменным типов float, double, void (или более сложных типов). Эти операции задаются следующими символами: ~ (поразрядное отрицание), << (сдвиг влево), >> (сдвиг вправо), & (поразрядное "И"), ^ (поразрядное исключающее "ИЛИ"), | (поразрядное "ИЛИ").
Примеры: если a = 0000 1111 и b = 1000 1000, то
~a = 1111 0000,
a << 1 = 0001 1110,
a >> 1 = 0000 0111,
a & b = 0000 1000,
a ^ b = 1000 0111,
a | b = 1000 1111.
В языке предусмотрены две нетрадиционные операции инкремента (++) и декремента (--). Они предназначены для увеличения и уменьшения на единицу значения операнда. Операции ++ и -- можно записывать как перед операндом, так и после него. В первом случае (++n или --n) значение операнда (n) изменяется перед его использованием в соответствующем выражении, а во втором (n++ или n--) - после его использования. Рассмотрим две следующие строки программы:
a = b + c++;
a1 = b1 + ++c1;
Предположим, что b = b1 = 2, c = c1 = 4. Тогда после выполнения операций: a = 6, b = 2, c = 5, a1 = 7, b1 = 2, c1 = 5.
Широкое распространение находят также выражения с еще одной нетрадиционной тернарной или условной операцией ?:. В формуле
y = x ? a: b;
y = a, если x не равно нулю (т.е. истинно), и y = b, если х равно нулю (ложно). Следующее выражение
y = (a>b) ? a: b;
позволяет присвоить переменной у значение большей переменной (а или b), т.е. y = max(a, b).
Еще одним отличием языка является то, что выражение вида а = а + 5; можно записать в другой форме: a += 5;. Вместо знака + можно использовать и символы других бинарных операций (см. табл. 2).
Другие операции из табл. 2 будут описаны в последующих параграфах.