Порядок, приоритет и правила вычислений
1. Порядок, приоритет и правила вычислений. Преобразование типов.
В таблице показаны приоритеты и очередность вычислений всех операторов. Операторы, перечисленные на одной строке, имеют одинаковый приоритет; строки упорядочены по убыванию приоритетов; так, например, *, / и % имеют одинаковый приоритет, который выше, чем приоритет бинарных + и -. “Оператор” () относится к вызову функции. Операторы -> и . (точка) обеспечивают доступ к элементам структур; Оператор *(косвенное обращение по указателю) и & (получение адреса объекта).
Операторы | Выполняются |
() [] -> | Слева направо |
! ~ ++ -- + - * & sizeof | Рекомендуемые материалыЛР2- 22Р (граф Ашкинузе) Отчет + код 6 lab вариант 13 Отчет по практикуму объектно-ориентированное программирование FREE Справочные материалы для выполнения лабораторных и контролируемых самостоятельных работ FREE РК2 по инфе Справа на лево |
* / % | Слева направо |
+ - | Слева направо |
<< >> | Слева направо |
< <= > => | Слева направо |
== != | Слева направо |
& | Слева направо |
^ | Слева направо |
| | Слева направо |
&& | Слева направо |
|| | Слева направо |
?: | Справа налево |
= += -+ *= /= %= &= ^= |= <<= >>= | Справа налево |
, | Слева направо |
Заметим, что приоритеты побитовых операторов &,^ и | ниже, чем приоритетов == и !=, из за чего в побитовых проверках, таких как
If ((x&MASK == 0) …
чтобы получить правильный результат, приходится использовать скобки.
Си подобно многим языкам не фиксирует очередность вычисления операндов оператора(за исключением &&, //, ?:, и ,). Например, в инструкции вида
x=f() + g();
f может быть вычислена раньше чем g или наоборот. Из этого следует, что если одна из функций изменяет значение переменной, от которой зависит другая функция, то помещаемый в x результат может зависеть от очередности вычислений.
Очередность вычисления аргументов функции также не определена, поэтому на разных компиляторах
Printf(“%d %dn”, ++n, power(2,n)); /*НЕВЕРНО*/
Может давать несовпадающие результатыю Результат вызова функции зависит от того, когда компилятор сгенерирует команды увеличения n – до или после обращения к power. Чтобы обезопасить себя от возможности побочного эффекта, достаточно написать
Рекомендуем посмотреть лекцию "10.8. Методика расследования преступлений".
++n;
Printf(“%d %dn”, n, power(2,n));
Если лперанды оператора принадлежат к разным типам, то они приводятся к некоторому общему типу. Приведение выполняются в соответствии с небольшим числом правил. Обычно автоматически производятся лишь те преобразования, которые без какой-либо потери информации превращают операнды с меньшим диапазоном значений в операнды с большим диапазоном, как, например, преобразование целого в число с плавающей точкой в выражении вроде f + i.Выражения, не имеющие смысла, например число с плавающей точкой в роли индекса, не допускаются. Выражения, в которых могла бы теряться информация( скажем, при присваивании длинных целых переменным более коротких типов или при присваивании значении с плавающей точкой целым переменным), могут повлечь за собой предупреждение, но они допустимы.
Неявные арифметические преобразования, как правило, осуществляются естественным образом. В общем случае, когда оператор вроде + или * с двумя операндами имеет разнотипные операнды, прежде чем операция начнет выполняться, “низший” тип повышается до “высшего”. Если же в выражении нет беззнаковых операндов, можно удовлетвориться следующим набором неформальных правил:
- Если какой-либо из операндов принадлежит типу long double, то и другой приводится к long double.
- В противном случае, если какой-либо из операндов принадлежит типу double, то и другой приводится к double.
- В противном случае, если какой-либо из операндов принадлежит типу float, то и другой приводится к float.
- В противном случае операнды типов char и short приводятся к int.
- И наконец, если один из операндов типа long, то и другой приводится к long.
Преобразования имеют место и при присвоениях: значение правой части присвоения приводится к типу левой части, которой и является типом результата.
Если х принадлежит типу float, а i – типу int, то и x=i и i=x вызовут преобразования, причем перевод float в int сопровождается отбрасыванием дробной части. Если double переводится во float, то значение либо округляется, либо обрезается. Это зависит от реализации.