I've been thinking of some beginner mistakes and I ended up with the one on the if
statement. I expanded a bit the code to this:
int i = 0;
if (i = 1 && i == 0) {
std::cout << i;
}
I have seen that the if
statement returns true, and it cout
's i
as 1
. If i
is assigned 1
in the if statement, why did i == 0
return true
?
i
is set to 1
.
1 && i == 0
?
This has to do with operator precedence.
if (i = 1 && i == 0)
is not
if ((i = 1) && (i == 0))
because both &&
and ==
have a higher precedence than =
. What it really works out to is
if (i = (1 && (i == 0)))
which assigns the result of 1 && (i == 0)
to i
. So, if i
starts at 0
then i == 0
is true
, so 1 && true
is true
(or 1
), and then i
gets set to 1
. Then since 1
is true, you enter the if block and print the value you assigned to i
.
Assuming your code actually looks like this:
#include <iostream>
using namespace std;
int main() {
int i = 0;
if (i = 1 && i == 0) {
cout << i;
}
}
Then this:
if (i = 1 && i == 0) {
evaluates as
if (i = (1 && i == 0)) {
and so i
is set to 1
.
using namespace std
!
=
came before &&
can see the issue. Also, yes, the expansion is extraneous, but I don't think it matters that much. I can't believe such minor differences cause people to vote 151 to -4.
The actual answer is:
The compiler gives precedence to "i == 0", which evaluates to true. Then it will evaluate i=1 as TRUE or FALSE, and since compiled assignment operators never fail (otherwise they wouldn't compile), it also evaluates to true. Since both statements evaluate as true, and TRUE && TRUE evaluates to TRUE, the if statement will evaluate to TRUE.
As proof, just look at the asm output of your compiler for the code you entered (all comments are my own):
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
The asm output above was from CLANG, but all other compilers I looked at gave similar output. This is true for all the compilers on that site, whether they are pure C or C++ compilers, all without any pragmas to change the mode of the compiler (which by default is C++ for the C++ compilers)
Note that your compiler did not actually set i=1, but i=TRUE (which means any 32-bit not zero integer value). That's because the && operator only evaluates whether a statement is TRUE or FALSE, and then sets the results according to that result. As proof, try changing i=1 to i=2 and you can observe for yourself that nothing will change. See for yourself using any online compiler at Compiler Explorer
i = 1
is an assignment [not an equivalence] operator; 2b) I can assure you that if (i = 0)
will evaluate to false condition in both C and C++, so whether it evaluates to true wrt "it never fails" is somewhat misleading.
and cl, 1 ; = operator always TRUE
<< correct me if I am wrong, but I see no assignation here. It represents the 1 &&
part of the expression. So this answer basically evaluates to false
.
if ( i = 0 ) { print something }
. Also your answer contradicts itself; at the start you say that i=1
is evaluated before &&
is applied, and then at the end you say that i
is set to the result of the &&
operator.
It has to do with parsing an the right to left rules. Eg y = x+5. All sub-expressions are weighted in importance. Two expressions of equal importance are evaluated right to left, . The && expression side is done first, followed by the LHS.
Makes sense to me.
Success story sharing
i = !i; if (i)
properly written