Почему в C/C++ нет оператора ^^?
-
10-07-2019 - |
Вопрос
&
имеет &&
. |
имеет ||
.Почему не ^
иметь ^^
?
Я понимаю, что это не будет коротким замыканием, но у него будет другая семантика.В С, true
на самом деле является любым ненулевым значением.Побитовое исключающее ИЛИ не всегда совпадает с логическим исключающим ИЛИ:
int a=strcmp(str1,str2);// evaluates to 1, which is "true"
int b=strcmp(str1,str3);// evaluates to 2, which is also "true"
int c=a ^^ b; // this would be false, since true ^ true = false
int d=a ^ b; //oops, this is true again, it is 3 (^ is bitwise)
Поскольку вы не всегда можете полагаться на истинное значение 1
или -1
, не было бы ^^
оператор будет очень полезен?Мне часто приходится делать странные вещи вроде этого:
if(!!a ^ !!b) // looks strange
Решение
Существуют как исторические, так и практические причины, по которым нет оператора
^^
. Р>Практика такова: для оператора нет особой пользы. Суть
& amp;
и||
заключается в том, чтобы использовать их оценку короткого замыкания не только из соображений эффективности, но чаще для выразительности и правильности. < ш> [...]
В отличие от этого, оператор^^
всегда вынуждает вычислять обе ветви выражения, поэтому повышение эффективности отсутствует. Кроме того, ситуации, в которых действительно требуется^^
, довольно редки, хотя примеры могут быть созданы. Эти ситуации становятся все более редкими и странными, когда вы складываете оператор--if (cond1() ^^ cond2() ^^ cond3() ^^ ...) ...
выполняет последующее точно, когда нечетное число из
condx ()
истинно. Напротив, аналоги& amp;
и||
остаются достаточно правдоподобными и полезными.
Другие советы
Технически, один уже существует:
a != b
, поскольку это будет иметь значение true, если значение истинности операндов отличается.
Edit:
(!a) != (!b)
правильно, потому что мой ответ выше не работает для типов int
. Я удалю мой, если он добавит свой ответ.
Снова отредактируйте:
Может быть, я что-то забываю в C ++, но чем больше я об этом думаю, тем больше я удивляюсь, почему вы вообще пишете if (1 ^ 2)
. Цель для ^
состоит в том, чтобы исключить или два числа вместе (что означает другое число), а не преобразовывать их в логические значения и сравнивать их значения истинности.
Кажется, что это было бы странным предположением для дизайнера языка.
Для не-bool
операнды, я думаю, вам бы хотелось, чтобы a ^^ b
оцениваться как:
(a != 0) ^ (b != 0)
Что ж, у вас есть вариант выше, и у вас есть несколько вариантов, перечисленных в других ответах.
Оператор ^^
было бы излишним для bool
операнды.Говоря только о логических операндах, давайте в целях рассуждения представим, что ^
было только побитовым, и это ^^
существовал как логический XOR.Затем у вас есть следующие варианты:
&
- Побитовое И - всегда оценивается оба операнда.&&
- Логическое И - не всегда оцениваются оба операнда.|
- Побитовое ИЛИ - всегда оценивается оба операнда.||
- Логическое ИЛИ – не всегда оцениваются оба операнда.^
- Побитовое исключающее ИЛИ - всегда должны оцениваться оба операнда.^^
- Логическое исключающее ИЛИ – всегда должно оцениваться оба операнда.
Почему они не создали ^^
по существу преобразовать числовые значения в bool
s, а затем действовать как ^
?Это хороший вопрос.Возможно, потому, что это потенциально более запутанно, чем &&
и ||
, возможно, потому, что вы можете легко построить эквивалент ^^
с другими операторами.
Я не могу сказать, что было в головах Кернигана и Ричи, когда они изобрели C, но вы кратко упомянули, что «не будет короткого замыкания», и я предполагаю, что причина: не возможно реализовать это последовательно. Вы не можете замкнуть XOR, как вы можете И и ИЛИ, поэтому ^^ не может быть полностью параллельным & amp; & amp; и || Таким образом, авторы вполне могли бы решить, что создание операции, которая своего рода похожа на параллель с другими, но не совсем, было бы хуже, чем ее отсутствие вообще.
Лично я по главной причине использую & amp; & amp; и || для короткого замыкания, а не для битового. На самом деле я очень редко использую побитовые операторы вообще.
Еще один обходной путь для тех, которые опубликованы выше (даже если для этого требуется другая ветвь в коде):
if ( (a? !b : b ) )
это эквивалентно xor.
В Java оператор ^
действительно выполняет логическое XOR, когда используется с двумя логическими операндами (точно так же, как в & amp;
и |
в Java не короткое замыкание логического И и ИЛИ, соответственно, применительно к логическим значениям). Основное отличие от C / C ++ состоит в том, что C / C ++ позволяет смешивать целые и логические значения, а Java - нет.
Но я думаю, что это плохая практика - использовать целые числа как булевы. Если вы хотите выполнять логические операции, вам следует придерживаться либо значений bool
, либо целых чисел, равных 0 или 1. Тогда ^
отлично работает как логический XOR.
Аналогичным вопросом было бы спросить, как бы вы сделали не замыкающие накоротко логические AND и OR в C / C ++? Обычный ответ - использовать операторы & amp;
и |
соответственно. Но опять же, это зависит от того, являются ли значения bool
или 0 или 1. Если вы разрешите какие-либо целочисленные значения, то это тоже не сработает.
Независимо от случая за или против ^^
в качестве оператора, ваш пример с strcmp ()
отстой. Он не возвращает значение истины (истина или ложь), он возвращает отношение между своими входами, закодированное как целое число.
Конечно, любое целое число может интерпретироваться как значение истинности в C, и в этом случае 0 равно "false" и все другие значения являются «истинными», но это противоположно тому, что возвращает strcmp ()
.
Ваш пример должен начаться:
int a = strcmp(str1, str2) == 0; // evaluates to 0, which is "false"
int b = strcmp(str1, str3) == 0; // evaluates to 0, which is also "false"
Вы должны сравнить возвращаемое значение с 0, чтобы преобразовать его в правильное логическое значение, указывающее, были ли строки равными или нет.
С " правильным " логические значения, представленные канонически как 0 или 1, побитовый оператор ^
тоже работает намного лучше ...