Я слышал, что часто «все», кроме 0, правда. Но сейчас со мной происходят очень странные вещи … или я просто думаю, что делаю это правильно, а я нет. Вот что происходит:
Когда я хочу проверить, если эквивалентно б, я могу использовать NOT(a XOR b)
, Когда я проверил это для unsigned char
s, все было хорошо, например
unsigned char a = 5;
unsigned char b = 3;
unsigned char c = ~(a^b);
дал мне c == 249
:
является: 00000101
5
б является: 00000011
, что составляет 3.
~ (А ^ Ь) является: 11111001
, что составляет 249.
Теперь давайте попробуем это с bool
«S.
cout << ~(true^true) << ~(true^false) << ~(false^true) << ~(false^false) << endl;
cout << ~(~(true^true)) << ~(~(true^false)) << ~(~(false^true)) << ~(~(false^false)) << endl;
if (~(true^true) == true)
cout << "true";
else
cout << "false";
Это дает мне в консоли:
-1-2-2-1
0110
false
пока я ожидал, что первая строка будет:
1001
Спросив друга, он посоветовал мне попробовать !
вместо ~
и посмотреть, будет ли это работать правильно. И (я думаю) теперь это работает правильно. Но я не понимаю почему. Не должно ли логическое отрицание работать на bools?
Я слышал, что часто «все», кроме 0 это правда
Это действительно для условий, как, например, в операторе if (здесь и ниже я цитирую Стандарт C ++)
Значение условия, которое является выражением, является значением
выражение, контекстно преобразованное в bool для операторов, отличных от
переключатель
Например, если вы напишите как
if (~(true^true) )
cout << "true";
else
cout << "false";
вместо вашего фрагмента кода
if (~(true^true) == true)
cout << "true";
else
cout << "false";
или когда оператор логического отрицания !
используется
9 Операнд оператора логического отрицания! контекстуально
преобразован в bool (пункт 4); его значение истинно, если преобразованный
операнд ложный и ложный в противном случае. Тип результата — bool
Что касается оператора ==
затем
6 Если оба операнда имеют арифметический или перечислимый тип, обычный
арифметические преобразования выполняются для обоих операндов; каждый из
операторы должны выдавать true, если указанное соотношение истинно и
ложь, если это ложь.
Это в случае
if (~(true^true) == true)
применяется обычное арифметическое преобразование, то есть булево значение true преобразуется в целочисленное значение 1, и оно не равно выражению левого оператора, потому что внутреннее двоичное представление левого операнда отличается от 1, как показано в выводе вашего первого фрагмента кода. ,
Вы недооцениваете арифметические преобразования. Когда ты сказал ~e
для некоторого выражения e
целочисленного типа, значение сначала повышается по крайней мере доint
и то же самое для e1 ^ e2
(и для любых арифметических выражений, в этом отношении). Так true ^ true
первый операнды повышены до int
, уступая 1 ^ 1
, который действительно равен 0, и, таким образом, вы в конечном итоге ~0
, который на вашей платформе -1
,
Вы можете смутно осмыслить свою работу, преобразовав результат обратно в bool
:
std::cout << static_cast<bool>(~(true ^ true))
В вашей последней проблеме, так как у вас есть выражение с ==
оператор, в котором два операнда имеют разные типы, оба операнда переводятся в общий тип, который снова int
, а также -1
отличается от 1
, Опять же, вы можете преобразовать оба операнда в bool
сначала получить желаемое равенство.
Мета-урок заключается в том, что встроенные в C ++ операторы, действующие на целые числа, действительно работают только на int
и шире, но не на любом из более коротких типов (bool
, char
, short
) (и аналогичные соображения применимы к передаче целых чисел через многоточие). Хотя это может иногда вызывать некоторую путаницу, я полагаю, это также немного упрощает языковые правила. Это все часть наследия C в C ++.
Учитывая только ваш первый пример,
~(true^true)
Во-первых, операнды ^
повышены до int
, так что это эквивалентно
~(1^1)
Тогда xor, равный 1, сам по себе дает битовый шаблон с нулем, который независимо от int
представление обозначает значение 0:
~0
Это инвертирует каждый бит в шаблоне битов со всеми нулями для 0, в результате чего получается битовый шаблон со всеми битами 1, например, для 32-битных int
,
int( 0xFFFFFFFF )
С теперь почти универсальным представлением формы дополнения до двух целых чисел со знаком это тогда значение -1.
Ваш вывод поэтому
-1
~
немного НЕ.
например ~ 0 — 255 для неподписанного символа и 255! = true
,
Существует разница между логическим отрицанием и побитовым отрицанием. побитовое отрицание переворачивает биты в переменной, а логическое отрицание переворачивает логическое значение, то есть true / false. Рассмотрим, например, число 5, представленное в двоичном виде как 101. Если вы перевернете только биты (~ 5), вы получите 11111010, что не является ложным, потому что только все нули ложны в c ++. Но если вы вычислите (! 5), вы получите все нули, которые будут работать внутри условия.