На этом шаге мы приведем примеры использования логических операций.
Перечислим теперь логические операции:
Операция отрицания ! преобразует ненулевой ("истинный") операнд в 0, а нулевой ("ложный") операнд в 1. Например, можно использовать запись !inword вместо inword==0.
Логическая операция "И" возвращает значение "истина", если оба ее операнда имеют значение "истина", иначе она вырабатывает значение "ложь".
Выражения, связанные логическими операциями && и ||, вычисляются слева направо, причем вычисление значения выражения прекращается сразу же, как только становится ясно, будет ли результат истинен или ложен.
Пример 1. Иллюстрация применения логических операций и операций увеличения.
#include<iostream.h> main () { int x=1,y=1,z=0; x = x&&y||z; /* Операции 1 */ cout<<x<<" "; x = x || !y&&z; /* Операции 2 */ cout<<x<<" "; x = y=1; z = x++-1; /* Операции 3 */ cout<<x<<" "<<z<<" "; z += -x++ + ++y; /* Операции 4 */ cout<<x<<" "<<z<<" "; z = x/++x; /* Операции 5 */ cout<<x<<" "<<z<<" "; }
Результат работы программы:
1 1 2 0 3 0 4 1
Прокомментируем полученные результаты.
int x=1, y=1, z=0; x=x&&y||z;
Сопоставляем операции с операндами в соответствии с приоритетами операций.
x = (x&&y)||z; x = ((x&&y)||z); (x = (x&&y)||(z));
Логические операции выполняются слева направо. Считается, что значение операнда в логической операции есть "ложь" если операнд равен 0, и "истина", если операнд имеет любое другое значение.
(x = ((TRUE&&TRUE)||(z)); (x = (TRUE||z);
Если известно, что один из операндов логической операции "ИЛИ" (||) имеет значение "истина", то результат операции - "истина", независимо от значения другого операнда. Таким образом, в данном случае нет смысла продолжать вычисления дальше.
(x = TRUE); 1
x=1; y=1; z=0; x = x || !y&&z;
Сопоставляем операции с операндами в соответствии с приоритетами операций.
x = x||!y&&z; x = x||(!y)&&z; x = x||((!y)&&z); (x = (x||(!y)&&(z)));
Вычисляем слева направо:
(x = (TRUE||((!y)&&z))); (x = TRUE); (x = 1); 1
x = y=1; z = x++-1;
Вследствие приоритетов операций:
z = x++-1; z = (x++)-1; z = ((x++)-1); (z = ((x++)-1));
Операция ++, стоящая справа от операнда, представляет собой постфиксную операцию. Это означает, что x увеличится на 1 после того, как значение x будет использовано в выражении:
(z = (1-1)); x = 2; (z = 0) 0
x=2; y=1; z=0; z += -x++ + ++y;
Унарные операции выполняются справа налево, так что операция ++ выполнится перед операцией -.
z += -(x++) + (++y);
Фактически, если бы операция изменения знака выполнялась первой, выражение было бы некорректным, так как операции ++ и -- требуют, чтобы операндом было адресное значение; x есть адресное значение, а -x нет.
z += (-(x++)) + (++y); z += ((-(x++)) + (++y)); (z += ((-(x++)) + (++y)));
Вычисление выражения начинается изнутри:
(z += ((-2)+2)); x = 3; y = 2; (z += 0); 0
x=3; z=0; z = x/++x; z = x/(++x); z = (x/(++x)); (z = (x/(++x)));
При реализации этой программы мы получим z=1. Вы могли бы поддаться искушению вычислять это выражение "изнутри". Вначале было бы выбрано значение x, увеличено на 1, а потом уже пойдет деление на значение x. Но возникает вопрос: какое значение x нужно использовать в качестве делимого - старое (3) или новое (4)? Иными словами, что делается раньше - выбирается ли значение x, используемое в качестве делимого, или в x записывается его значение, увеличенное на 1. Описание языка C++ не определяет, что получается, если возникают такие побочные эффекты; их реализация остается за разработчиками трансляторов.
Побочным эффектом называется любое изменение результатов работы программы как следствие выполнения некоторого оператора. Большинство побочных эффектов в языке C++ связано с записью в память промежуточных значений переменных, которые, как выше, получаются в результате операции увеличения или в результате присваивания, встретившегося в выражении.
Отсюда - совет: избегайте выражений, вычисление которых зависит от
вашего знания того,
что происходит при побочных эффектах.
Мы закончили изложение логических операций. Следующий шаг будет посвящен
битовым операциям.