Почему этот оператор if, объединяющий присваивание и проверку на равенство, возвращает true?
Я думал о некоторых ошибках новичка, и я закончил тем, что на утверждении if
. Я немного расширил код до этого:
int i = 0;
if (i = 1 && i == 0) {
std::cout << i;
}
Я видел, что оператор if
возвращает true, и он cout
i
как 1
. Если i
присваивается 1
в операторе if, почему i == 0
вернул true
?
Ответы
Ответ 1
Это связано с приоритетом оператора.
if (i = 1 && i == 0)
не является
if ((i = 1) && (i == 0))
потому что и &&
, и ==
имеют более высокий приоритет, чем =
. То, к чему это действительно работает, -
if (i = (1 && (i == 0)))
который присваивает результат 1 && (i == 0)
i
. Итак, если i
начинается с 0
, то i == 0
- это true
, поэтому 1 && true
- это true
(или 1
), а затем для i
устанавливается значение 1
. Затем, поскольку 1
имеет значение true, вы вводите блок if и печатаете значение, назначенное для i
.
Ответ 2
Предполагая, что ваш код на самом деле выглядит так:
#include <iostream>
using namespace std;
int main() {
int i = 0;
if (i = 1 && i == 0) {
cout << i;
}
}
Тогда это:
if (i = 1 && i == 0) {
оценивает как
if (i = (1 && i == 0)) {
и поэтому i
установлен в 1
.
Ответ 3
Вопрос вводит в заблуждение.
В операторе if
"вы не совмещаете присваивание и проверку на равенство".
Как уже объяснялось другими, вы просто присваиваете результат комбинации двух истинных выражений переменной.
Это как спрашивать:
так как "4 + 5 * 2" (по моему мнению...) равно 18 почему
int i = 4 + 5 * 2;
std::cout << i;
печатает 14?
Ответ 4
У вас есть i = 1
меняет значение i
на 1
. Все значения, отличные от 0
каста для типа bool, дают true
. Так что у тебя всегда есть правда.
Ответ 5
Фактический ответ:
- Компилятор присваивает приоритет "i == 0", что соответствует истине.
- Затем он будет оценивать i = 1 как TRUE или FALSE, и поскольку скомпилированные операторы присваивания никогда не завершаются ошибкой (иначе они не будут компилироваться), он также оценивается как true.
- Поскольку оба утверждения оцениваются как истинные, и TRUE && TRUE оценивается как TRUE, оператор if будет иметь значение TRUE.
В качестве доказательства просто посмотрите на вывод asm вашего компилятора для кода, который вы ввели (все комментарии мои):
mov dword ptr [rbp - 8], 0 ; i = 0;
cmp dword ptr [rbp - 8], 0 ; i == 0?
sete al ; TRUE (=1)
mov cl, al
and cl, 1 ; = operator always TRUE
movzx edx, cl
mov dword ptr [rbp - 8], edx ; set i=TRUE;
test al, 1 ; al never changed,
; so final ans is TRUE
Приведенный выше вывод asm был из CLANG, но все остальные компиляторы, на которые я смотрел, давали похожий вывод. Это верно для всех компиляторов на этом сайте, будь то чистые компиляторы C или C++, все без каких-либо прагм для изменения режима компилятора (который по умолчанию равен C++ для компиляторов C++)
Обратите внимание, что ваш компилятор на самом деле не установил i = 1, но i = TRUE (что означает любое 32-битное не нулевое целое значение). Это потому что && Оператор только оценивает, является ли оператор TRUE или FALSE, а затем устанавливает результаты в соответствии с этим результатом. В качестве доказательства попробуйте изменить i = 1 на i = 2, и вы сами сможете убедиться, что ничего не изменится. Убедитесь сами, используя любой онлайн-компилятор в Compiler Explorer
Ответ 6
Это связано с разбором правил справа налево.
Например, у = х + 5.
Все подвыражения взвешены по важности.
Два выражения одинаковой важности оцениваются справа налево. & Amp; & Сначала выполняется выражение, затем LHS.
Имеет смысл для меня.