logo search
Подбельский Фомин_Программирование на языке СИ_

Унарные (одноместные) операции.

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

&

*

-

+

~

!

++

- операция получения адреса операнда (ранг 2);

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

- унарный минус, изменяет знак арифметического операнда (ранг 2),

- унарный плюс, введен для симметрии с унарным минусом (ранг 2);

- поразрядное инвертирование внутреннего двоичного кода целочисленного аргумента - побитовое отрицание (ранг 2);

- логическое отрицание (НЕ) значения операнда (ранг 2). Применяется к скалярным операндам. Целочисленный результат 0 (если операнд ненулевой, т.е. истинный) или 1 (если операнд нулевой, т.е. ложный). Напомним, что в качестве логических значений в языке используют целые числа: 0 - ложь и не нуль, т.е. (!0) - истина. Отрицанием любого ненулевого числа будет 0, а отрицанием нуля будет 1. Таким образом: !1 равно 0; !2 равно 0; !(-5) равно 0; !0 равно 1;

- увеличение на единицу (инкремент или автоувеличение - ранг 2); имеет две формы:

префиксная операция - увеличение значения операнда на 1 до его использования. Ассоциативность справа в соответствии со стандартом;

постфиксная операция - увеличение значения операнда на 1 после его использования. Ассоциативность слева в соответствии со стандартом.

Операнд для операции ++ (и для операции -) не может быть константой либо произвольным выражением. Записи ++5 или 84++ будут неверными. ++(j+k) также неверная запись. Операндами унарных операций ++ и — должны быть всегда модифицируемые именующие выражения (L-value, left value, l-значение, леводопустимое выражение). Термины "лево-допустимое выражение" и "l-значение" происходят от объяснения действия операции присваивания Е = D, в которой операнд Е слева от знака операции присваивания может быть только модифицируемым l - значением. Примером модифицируемого l-значения

- -

sizeof

служит имя переменной, которой выделена память.

Таким образом, l-значение - ссылка на область памяти, значение которой доступно изменениям;

- уменьшение на единицу (декремент или автоуменьшение - ранг 2) - унарная операция, операндом которой должно быть леводопустимое выражение, т.е. не константа и не выражение:

префиксная операция - уменьшение на 1 значения операнда до его использования;

постфиксная операция - уменьшение на 1 значения операнда после его использования;

- операция (ранг 2) вычисления размера (в байтах) для объекта того типа, который имеет операнд. Разрешены два формата операции:

sizeof выражение

sizeof (mun).

sizeof не вычисляет значения выражения, а только определяет его тип, для которого затем вычисляется размер.

Бинарные (двуместные) операции делятся на следующие группы:

• аддитивные;

• мультипликативные;

• сдвигов;

• поразрядные;

• операции отношений;

• логические;

• присваивания;

• выбора компонента структурированного объекта;

• операция "запятая";

• скобки в качестве операций.

Аддитивные операции:

+ - бинарный плюс - сложение арифметических операндов или сложение указателя с целочисленным операндом (ранг 4);

- - - бинарный минус - вычитание арифметических операндов или вычитание указателей (ранг 4).

Мультипликативные операции:

* - умножение операндов арифметического типа (ранг 3);

/ - деление операндов арифметического типа (ранг 3). При целочисленных операндах абсолютное значение результата округляется до целого. Например, 20/3 равно 6, -20/3 равно -6, (-20)/3 равно - 6, 20/(-3) равно -6;

% - получение остатка от деления целочисленных операндов (деление по модулю - ранг 3). При неотрицательных операндах остаток положительный. В противном случае остаток определяется реализацией. В компиляторе Turbo С:

13%4 равняется 1, (-13)%4 равняется -1;

13%(-4) равно +1, а (-13)%(-4) равняется -1.

При ненулевом делителе для целочисленных операндов всегда выполняется соотношение: (а/b)*b + а%b равно а.

Операции сдвига (определены только для целочисленных операндов). Формат выражения с операцией сдвига:

операнд_левый операция_сдвига операнд_правый

<< - сдвиг влево битового представления значения левого целочисленного операнда на количество разрядов, равное значению правого целочисленного операнда (ранг 5);

>> - сдвиг вправо битового представления значения левого целочисленного операнда на количество разрядов, равное значению правого целочисленного операнда (ранг 5).

Поразрядные операции:

& - поразрядная конъюнкция (И) битовых представлений значений целочисленных операндов (ранг 8);

I - поразрядная дизъюнкция (ИЛИ) битовых представлений значений целочисленных операндов (ранг 10);

А - поразрядное исключающее ИЛИ битовых представлений значений целочисленных операндов (ранг 9).

Результат выполнения операций сдвига и поразрядных операций:

4<< 2 равняется 16;

5>>1 равняется 2;

6&5 равняется 4;

6 | 5 равняется 7;

6 ^ 5 равняется 3.

Напоминаем, что двоичный код для 4 равен 100, для 5 - это 101, для 6 - это 110 и т.д. При сдвиге влево на две позиции код 100 становится равным 10000 (десятичное значение равно 16). Остальные результаты операций сдвига и поразрядных операций могут быть прослежены аналогично.

Обратите внимание, что сдвиг влево на п позиций эквивалентен умножению значения на 2", а сдвиг кода вправо уменьшает соответствующее значение в 2" раз с отбрасыванием дробной части результата. (Поэтому 5>>1 равно 2.)

Операции отношений (сравнения):

< меньше, чем (ранг 6);

> больше, чем (ранг 6);

<= меньше или равно (ранг 6);

>= больше или равно (ранг 6);

= равно (ранг 7);

!= не равно (ранг 7).

Операнды операций отношений должны быть арифметического типа или могут быть указателями. Результат целочисленный: 0 (ложь) или 1 (истина). Последние две операции (операции сравнения на равенство) имеют более низкий приоритет по сравнению с остальными операциями отношений. Таким образом, выражение (х < В == А < х) есть 1 тогда и только тогда, когда значение х находится в интервале от А до В и А< В. (Вначале вычисляются х < В и А < х, а к результатам применяется операция сравнения на равенство = =.)

Логические бинарные операции:

&& - конъюнкция (И) арифметических операндов или отношений (ранг 11). Целочисленный результат 0 (ложь) или 1 (истина);

| | - дизъюнкция (ИЛИ) арифметических операндов или отношений (ранг 12). Целочисленный результат 0 (ложь) или 1 (истина).

(Вспомните о существовании унарной операции отрицания'!'.)

Результаты отношений и логических операций:

3<5 равняется 1;

3>5 равняется 0;

3=5 равняется 0;

3!=5 равняется 1;

3!=5 || 3= =5 равняется 1;

3+4>5 && 3+5>4 && 4+5>3 равняется 1.

Операции присваивания (ранг 14)

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

Перечислим операции присваивания, отметив, что существуют одна простая операция присваивания и ряд составных операций:

= - простое присваивание: присвоить значение выражения-операнда из правой части операнду левой части. Пример: Р = 10.3 - 2*х;

*= - присваивание после умножения: присвоить операнду левой части произведение значений обоих операндов. Р *= 2 эквивалентно Р = Р * 2;

/= - присваивание после деления: присвоить операнду левой части частное от деления значения левого операнда на значение правого. Р /= 2.2 - d эквивалентно Р = Р / (2.2 - d);

%= - присваивание после деления по модулю: присвоить операнду левой части остаток от целочисленного деления значения левого операнда на значение правого операнда. N %= 3 эквивалентно N = N % 3;

+= - присваивание после суммирования: присвоить операнду левой части сумму значений обоих операндов А += В эквивалентно А = А + В;

-= - присваивание после вычитания: присвоить операнду левой части разность значений левого и правого операндов. X -= 4.3 - Z эквивалентно X = X - (4.3 - Z);

<<= - присваивание после сдвигов разрядов влево: присвоить целочисленному операнду левой части значение, полученное сдвигом влево его битового представления на количество разрядов, равное значению правого целочисленного операнда. Например, а <<= 4 эквивалентно а = а << 4;

>>= - присваивание после сдвигов разрядов вправо: присвоить целочисленному операнду левой части значение, полученное сдвигом вправо его битового представления на количество разрядов, равное значению правого целочисленного операнда. Например, а >>= 4 эквивалентно а = а >> 4;

&= - присваивание после поразрядной конъюнкции: присвоить целочисленному операнду левой части значение, полученное поразрядной конъюнкцией (И) его битового представления с битовым представлением целочисленного операнда правой части е & = 44 эквивалентно е = е & 44;

| = - присваивание после поразрядной дизъюнкции: присвоить целочисленному операнду левой части значение, полученное поразрядной дизъюнкцией (ИЛИ) его битового представления с битовым представлением целочисленного операнда правой части а | = b эквивалентно а = а | b;

^= - присваивание после исключающего поразрядного "ИЛИ": присвоить целочисленному операнду левой части значение, полученное применением поразрядной операции исключающего ИЛИ к битовым представлениям значений обоих операндов z^=x+y эквивалентно z = z ^ (х + у).

Обратите внимание, что для всех составных операций присваивания форма присваивания Е1 ор= Е2 эквивалентна Е1 = El op (E2), где ор - обозначение операции.

Операции выбора компонентов структурированного объекта:

. (точка) - прямой выбор (выделение) компонента структурированного объекта, например объединения или структуры (ранг 1). Формат применения операции:

имя структурированного _объекта. имя_компонента

-> - косвенный выбор (выделение) компонента структурированного объекта, адресуемого указателем (ранг 1). При использовании операции требуется, чтобы с объектом был связан указатель (указателям посвящена гл. 4.). В этом случае формат применения операции имеет вид: указатель_наструктурированный_объект -> имя_компонента

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

Запятая в качестве операции (ранг 15)

Несколько выражений, разделенных запятыми ",", вычисляются последовательно слева направо. В качестве результата сохраняются тип и значение самого правого выражения. Таким образом, операция "запятая" группирует вычисления слева направо. Тип и значение результата определяются самым правым из разделенных запятыми операндов (выражений). Значения всех левых операндов игнорируются. Например, если переменная х имеет тип int, то значением выражения (х=3, 3*х) будет 9, а переменная х примет значение 3.

Скобки в качестве операций

Круглые ( ) и квадратные [ ] скобки играют роль бинарных операций (ранг 1) при вызове функций и индексировании элементов массивов. Для программиста, начинающего использовать язык Си, мысль о том, что скобки в ряде случаев являются бинарными операциями, часто даже не приходит в голову. И это даже тогда, когда он практически в каждой программе обращается к функциям или применяет индексированные переменные. Итак, отметим, что скобки могут служить бинарными операциями, особенности и возможности которых достойны внимания.

Круглые скобки обязательны в обращении к функции:

имя_функции(список_аргументов)

где операндами служат имя_функции и список_аргументов. Результат вызова определяется (вычисляется) в теле функции, структуру которого задает ее определение.

В выражении

имя_массива[индекс]

операндами для операции [ ] служат имя_массива и индекс. Подробнее с индексированными переменными мы познакомимся на примерах в главе 2 и более подробно в следующих главах.

Условная трехместная операция (ранг 13). В отличие от унарных и бинарных операций условная тернарная операция используется с тремя операндами. В изображении условной операции применяются два символа '?' и ':' и три выражения-операнда:

выражение_1 ? выражение_ 2 : выражение_3

Первым вычисляется значение выражения_1. Если оно истинно, т.е. не равно нулю, то вычисляется значение выражения_2, которое становится результатом. Если при вычислении выражения_1 получится 0, то в качестве результата берется значение выражения_3. Классический пример:

х < 0 ? -х : х;

Выражение возвращает абсолютную величину переменной х.

Операция явного преобразования типа. Операция преобразования (приведения) типа (ранг 2) имеет следующий формат:

(имя_типа) операнд

Такое выражение позволяет преобразовывать значение операнда к заданному типу. В качестве операнда используется унарное выражение, которое в простейшем случае может быть переменной, константой или любым выражением, заключенным в круглые скобки. Например, преобразования (Iong)8 (внутреннее представление результата имеет длину 4 байта) и (char)8 (внутреннее представление результата имеет длину 1 байт) изменяют длину внутреннего представления целых констант, не меняя их значений.

В этих преобразованиях константа не меняла значения и оставалась целочисленной. Однако возможны более глубокие преобразования, например, (long double)6 или (float)4 не только изменяют длину константы, но и структуру ее внутреннего представления. В результатах будут выделены порядок и мантисса, значения будут вещественными.

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