Целочисленные значения Bool дают противоположный результат ожидаемому
Непонятно я написал код, чтобы проверить, что все значения структуры были установлены равными 0. Для этого я использовал:
bool IsValid() {
return !(0 == year == month == day == hour == minute == second);
}
где все члены структуры имели тип unsigned short. Я использовал код как часть более крупного теста, но заметил, что он возвращал значение false для значений, отличных от нуля, и true для значений, которые были равны нулю - напротив того, что я ожидал.
Я изменил код, чтобы читать:
bool IsValid() {
return (0 != year) || (0 != month) || (0 != day) || (0 != hour) || (0 != minute) || (0 != second);
}
Но хотелось бы знать, что вызвало нечетное поведение. Это результат приоритета? Я попытался ответить на этот ответ Google, но ничего не нашел, если есть какая-либо номенклатура, чтобы описать результат, который я хотел бы узнать.
Я скомпилировал код, используя VS9 и VS8.
Ответы
Ответ 1
==
группы слева направо, поэтому, если все значения равны нулю, то:
0 == year // true
(0 == year) == month // false, since month is 0 and (0 == year) converts to 1
((0 == year) == month) == day // true
И так далее.
В общем случае x == y == z
не эквивалентен x == y && x == z
, как вы, кажется, ожидаете.
Ответ 2
Поведение не должно рассматриваться как нечетное. Правила грамматики для ==
(и большинства, но не всех двоичных операторов) определяют группировку слева направо, поэтому ваше исходное выражение эквивалентно:
!((((((0 == year) == month) == day) == hour) == minute) == second)
Обратите внимание, что по сравнению с целым типом выражение bool
со значением true
будет продвигаться до 1
и со значением false
будет продвигаться до 0
. (В C результатом оператора равенства является int
в любом случае со значением или либо 1
, либо 0
.)
Это означает, что, например, ((0 == year) == month)
будет истинным, если year
равно нулю и month
является одним или если year
отличен от нуля, но month
равен нулю и false в противном случае.
Ответ 3
Вы должны рассмотреть, как он оценивается...
a == b == c
спрашивает, являются ли два из них равными (a
и b
), а затем сравнивая этот логический результат с третьим значением c
! Это НЕ сравнение первых двух значений с третьим. Все, что находится за пределами 2 аргументов, не будет цепочки, как вы, очевидно, ожидаете.
Что бы это ни стоило, потому что С++ считает, что значения не-0 являются "истинными" в булевом контексте, вы можете выразить то, что хотите, просто как:
return year && month && day && hour && minute && second;
(обратите внимание: ваш обновленный код дважды говорит "месяц" и не проверяет минуту).
Вернемся к цепочке ==
s: с пользовательскими типами и перегрузкой оператора вы можете создать класс, который сравнивается по мере того, как вы ожидаете (и он может даже позволить таким вещам, как 0 <= x < 10
"работать" таким образом, чтобы он читал в математике), но создание чего-то особенного будет просто путать других программистов, которые уже знают (странный) способ, которым эти вещи работают для встроенных типов на С++. Стоит делать 10-20-минутное программирование, хотя, если вы хотите изучить С++ по глубине (подсказка: вам нужны операторы сравнения, чтобы вернуть прокси-объект, который помнит, что будет левым для следующего сравнения оператор).
Наконец, иногда эти "странные" булевы выражения полезны: например, a == b == (c == d)
может быть сформулирован на английском языке как "либо (a == b), и (c == d), OR (a!= b) и (c!= d)", или, возможно, "эквивалентность a и b такая же, как эквивалентность c и d (истинна или ложна не имеет значения)". Это может привести к моделированию ситуаций в реальном мире, таких как сценарий двойного знакомства: если нравится/не нравится b (их дата) до тех пор, пока c не нравится/не нравится d, тогда они либо будут болтаться, либо хорошо проводить время, либо называть его быстрым и быстрым это безболезненно в любом случае... иначе у одной пары будет очень утомительное время... Потому что эти вещи могут иметь смысл, невозможно, чтобы компилятор знал, что вы не собираетесь создавать такое выражение.
Ответ 4
Возврат оператора ==
равен 1
, если операнды равны, поэтому, несмотря на то, что это читается слева направо или справа налево, это не будет делать то, что вы ожидаете.
поэтому это может работать только в аналогичном тесте, если вам будет интересно, если все значения 1
.
И чтобы иметь более короткое выражение, так как вы заинтересованы в том, что просто year || day || ...
Ответ 5
Ваша ошибка здесь заключается в написании математического выражения с использованием знаков равенства и немыслимо, предполагая, что компьютер выполнит ваш тест, что человеческий математик увидит в качестве значения этих символов. Что делает компьютер (в соответствии с определением языка), это выполнить серию дискретных сравнений, каждый из которых возвращает true
или false
- и этот true
или false
затем используется в следующем сравнении, Вы не сравниваете все эти переменные с 0, вы сравниваете каждый (два из них) с результатом сравнения двух других переменных.