Сокращенная запись операции присваивания

В языке Си используются два вида сокращенной записи операции присваивания:

1) вместо записи: v = v # e;

где # – любая арифметическая операция (операция над битовым представлением операндов), рекомендуется использовать запись v #= e;

Например, i = i + 2; « i += 2; (знаки операций – без пробелов);

2) вместо записи: x = x # 1;

где # – символы, обозначающие операцию инкремента (+1), либо декремента (–1), x – целочисленная переменная (или переменная-указатель), рекомендуется использовать запись:

##x; – префиксную, или x##; – постфиксную.

Если эти операции используются в чистом виде, то различий между постфиксной и префиксной формами нет. Если же они используются в выражении, то в префиксной форме (##x) сначала значение x изменится на 1, а затем полученный результат будет использован в выражении; в постфиксной форме (x##) – сначала значение переменной х используется в выражении, а затем изменится на 1. Операции над указателями будут рассмотрены в разд. 9.4.

 

Пример 1:   Пример 2:  
int i, j, k; Смысл записи int n, a, b, c, d; Значения
float x, y;   n = 2; a = b = c = 0;  
...   a = ++n; n=3, a=3
х *= y; x = x*y; a += 2; a=5
i += 2; i = i + 2; b = n++; b=3, n=4
x /= y+15; x = x/(y + 15); b –= 2; b=1
--k; k = k – 1; c = --n; n=3, c=3
k--; k = k – 1; c *= 2; c=6
j = i++; j = i; i = i + 1; d = n--; d=3, n=2
j = ++i; i = i + 1; j = i; d %= 2; d=1

 

 

Преобразование типов операндов арифметических операций

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

Но, как правило, в операциях участвуют операнды различных типов. В этом случае они преобразуются к общему типу в порядке увеличения их «размера памяти», т.е. объема памяти, необходимого для хранения их значений. Поэтому неявные преобразования всегда идут от «меньших» объектов к «большим». Схема выполнения преобразований операндов арифметических операций выглядит следующим образом:

short, char ® int ® unsigned ® long ® double
      float ® double

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

– значения типов char и short всегда преобразуются в int;

– если один из операндов имеет тип double, то и другой преобразуется в double;

– если один из операндов long, то другой преобразуется в long.

Внимание. Результатом операции 1/3 будет значение 0, чтобы избежать такого рода ошибок, необходимо явно изменить тип хотя бы одного операнда, т.е. записать, например: 1./3 .

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

При выполнении операции присваивания значение правого операнда преобразуется к типу левого, который и является типом полученного результата. И здесь необходимо быть внимательным, т.к. при некорректном использовании операций присваивания могут возникнуть неконтролируемые ошибки. Так, при преобразовании int в char старший байт просто отбрасывается.

Пусть: float x; int i; тогда и x = i; и i = x; приводят к преобразованиям, причем float преобразуется в int отбрасыванием дробной части.

Тип double преобразуется в float округлением.

Длинное целое преобразуется в более короткое целое и char посредством отбрасывания бит в старших разрядах.

Итак, безопасным преобразованием типов является преобразование в порядке увеличения «размера памяти», обратное преобразование может привести к потере значащих разрядов.

 

Операция приведения типа

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

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

ее результат – значение выражения, преобразованное к заданному типу.

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

double x;

int n = 6, k = 4;

x = (n + k)/3; ® x = 3, т.к. дробная часть будет отброшена;

x = (double)(n + k)/3; ® x = 3.333333 – использование операции приведения типа позволило избежать округления результата деления целочисленных операндов.

 

Операции сравнения

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

== – равно или эквивалентно; != – не равно;

< – меньше; <= – меньше либо равно;

> – больше; >= – больше либо равно.

Пары символов соответствующих операций разделять нельзя.

Общий вид операций отношений:

Операнд_1 Знак операции Операнд_2

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

Значения арифметических выражений перед сравнением вычисляются и преобразуются к одному типу.

Арифметические операнды преобразуются по правилам, аналогичным для арифметических операций. Операнды-указатели преобразуются в целые числа необходимого типа. Результат сравнения указателей будет корректным в арифметическом смысле лишь для объектов одного массива.

В языке Си нет логического типа данных. Результат операции отношения имеет значение 1, если отношение истинно, или в результате вычислений получено не нулевое значение, воспринимаемое компилятором Си как истина (true), или 0 – в противном случае, т.е. – ложно (false). Следовательно, операция отношения может использоваться в любых арифметических выражениях.

Операции сравнения на равенство и неравенство имеют меньший приоритет, чем остальные операции отношений.

Примеры использования операций отношений:

y > 0 , x == y , x != 2 .

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

 

Логические операции

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

! – отрицание (логическое «НЕТ»);

&& – конъюнкция (логическое «И»);

|| – дизъюнкция (логическое «ИЛИ»).

Операндами (выражениями) логических операций могут быть любые скалярные типы. Ненулевое значение операнда трактуется как «истина», а нулевое – «ложь». Результатом логической операции, как и в случае операций отношения, может быть 1 или 0.

Общий вид операции отрицания

! выражение

Примеры использования операции отрицания:

!0 ® 1

!5 ® 0

x = 10;

! (x > 0) ® 0

Общий вид операций конъюнкции и дизъюнкции:

Выражение_1 знак операции Выражение_2

Особенность операций конъюнкции и дизъюнкции – экономное последовательное вычисление выражений-операндов:

– если выражение_1 операции «конъюнкция» ложно, то результат операции – ноль и выражение_2 не вычисляется;

– если выражение_1 операции «дизъюнкция» истинно, то результат операции – единица и выражение_2 не вычисляется.

Например:

y > 0 && x = 7 ® истина, если оба выражения истинны;

e > 0 || x = 7 ® истина, если хотя бы одно выражение истинно.

Старшинство операции «И» выше, чем «ИЛИ» и обе они младше операций отношения и равенства.

Относительный приоритет логических операций позволяет пользовать­ся общепринятым математическим стилем записи сложных логических выражений, например:

0 < x < 100 « 0 < x && x < 100 ;

x > 0, y £ 1 « x > 0 && y <=1 .

Учет этих свойств очень существенен для написания правильно работающих программ.