В чем смысл логических операторов в C?

Мне просто интересно, есть ли в C логический оператор XOR (что-то вроде && для AND, но для XOR). Я знаю, что могу разделить XOR на AND, NOT и OR, но простой XOR был бы намного лучше. Затем мне пришло в голову, что если я использую обычный побитовый оператор XOR между двумя условиями, он может просто сработать. И для моих тестов это было так.

Учитывать:

int i = 3;
int j = 7;
int k = 8;

Просто ради этого довольно глупого примера, если мне нужно, чтобы k было либо больше, чем i, либо больше, чем j, но не оба, XOR было бы весьма кстати.

if ((k > i) XOR (k > j))
   printf("Valid");
else
   printf("Invalid");

or

printf("%s",((k > i) XOR (k > j)) ? "Valid" : "Invalid");

Я поставил побитовое XOR ^, и получилось "Invalid". Помещение результатов двух сравнений в два целых числа привело к тому, что два целых числа содержат 1, следовательно, XOR дало ложное. Затем я попробовал это с помощью & и | побитовые операторы, и оба дали ожидаемые результаты. Все это имеет смысл, зная, что истинные условия имеют ненулевое значение, в то время как ложные условия имеют нулевые значения.

Мне было интересно, есть ли причина использовать логические && и || когда поразрядные операторы &, | и ^ работать точно так же?


person reubensammut    schedule 05.05.2010    source источник
comment
Возможный дубликат логического оператора XOR в C ++?   -  person phuclv    schedule 12.04.2016


Ответы (5)


Вам не нужен логический XOR, я забыл вопрос SO, но он похож на то, что вы думаете, в основном нам не нужен XOR, он в любом случае эквивалентен ! =

FALSE XOR FALSE == FALSE
FALSE XOR TRUE == TRUE
TRUE XOR FALSE == TRUE
TRUE XOR TRUE == FALSE


FALSE != FALSE == FALSE
FALSE != TRUE == TRUE
TRUE != FALSE == TRUE
TRUE != TRUE == FALSE

Я поищу в избранном и вставлю ссылку позже ...

person Michael Buen    schedule 05.05.2010
comment
&, | и ^ могут работать так же, как || и && при использовании для значений логических, но обычно вы не используете &, | и ^ для логических значений - вы используете их для работы с биты (поэтому они побитовые операторы). При правильном использовании побитовые операторы не совпадают с логическими операторами. - person mipadi; 05.05.2010
comment
исторически побитовые операторы и логические операторы используют общий токен (то есть & и |), && и || еще нет stackoverflow.com/questions/3930042/ Проверьте Neonatal C: cm.bell-labs.com/cm/cs/who/dmr/chist.html И очень жаль, что они сохранили старый приоритет операторов & и |, когда они добавили && и || в C. Отсюда и эта неудачная скобка (sic) в идиоме маскировки: if ( (input & alt) == alt ). В противном случае это могло бы быть более лаконично: if ( input & alt == alt ) - person Michael Buen; 01.01.2011
comment
Это не правда. ! = не является логическим xor. Смотрите: 2 LOGICAL_XOR 4 дает false (что верно), но 2 != 4 дает true (что неверно). Правильный ответ ниже (Джо Д. ответ) - person Yury; 26.10.2011
comment
Поскольку спрашивающий спросил о логическом операторе, оба числа необходимо было правильно уменьшить до логических значений, прежде чем применять какой-либо оператор / макрос к обоим логическим значениям. Просто примените двойные знаки отличия с каждой стороны выражения. !! 2! = !! 4 дает ложь. т.е. истина! = истина дает ложь - person Michael Buen; 26.10.2011
comment
!! это наиболее идиоматический способ уменьшить число до логического. Если есть какая-то другая техника, я был бы более чем рад узнать :-) - person Michael Buen; 26.10.2011

Побитовые операторы не работают «точно так же», как && и || оператор. Для начала, && и || выполняют краткую оценку, тогда как побитовые операторы этого не делают. Другими словами, вы не можете сделать что-то подобное с поразрядными операторами:

int * p = 0;
(p != 0) && (*p = 1);

потому что если вы сказали:

(p != 0) & (*p = 1);

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

person Community    schedule 05.05.2010
comment
Внутренне нет, но я все равно получил те же результаты - person reubensammut; 05.05.2010
comment
@reubensammut: Вы не получите тех же результатов, если будете зависеть от короткого замыкания. if(returnsTrue() || explodesWorld()) не уничтожит мир, а if(returnsTrue() | explodesWorld()) уничтожит. - person unwind; 05.05.2010

Побитовое исключающее ИЛИ не работает так же, как логическое ИЛИ, если его операнды являются целочисленными значениями:

2^4 ? "Valid" : "Invalid"

дает "Действительный", но должен выдавать "Недействительный"

person mouviciel    schedule 05.05.2010
comment
Я имел в виду XOR при использовании для условий - person reubensammut; 05.05.2010
comment
В языке C 2 - допустимый способ выражения ИСТИНА. Многие используют его для проверки указателя NULL: if (!p) ... - person mouviciel; 05.05.2010

В C аргументы логических операторов обрабатываются как логические значения - все, что ноль, рассматривается как «ложь», а все остальное (да, отрицательные значения тоже) - «истина». Побитовые операции работают с отдельными битами и, как уже заметил Нил, не подвержены оценке короткого замыкания, как логические операции.

В вашем примере результаты полностью действительны и ожидаемы, поскольку побитовое xor между двумя равно нулю.

person Nikolai Fetissov    schedule 05.05.2010

Если вам нужен логический оператор xor в C, вы можете использовать это:

#define xor != 0 ^ !!

Он работает, преобразуя обе стороны выражения в логические значения и оценивая их. Вы можете использовать его, как если бы вы использовали && или ||, например:

if (a xor b)

AFAICT, никаких проблем с этим нет.

person Joe D    schedule 30.05.2010