A resposta real é:
- O compilador dá precedência para "i == 0", que é avaliado como verdadeiro.
- Em seguida, ele avaliará i = 1 como VERDADEIRO ou FALSO, e como os operadores de atribuição compilados nunca falham (caso contrário, não compilariam), ele também avalia como verdadeiro.
- Como as duas instruções são avaliadas como verdadeiras e TRUE && TRUE é avaliada como TRUE, a instrução if será avaliada como TRUE.
Como prova, basta olhar para a saída asm do seu compilador para o código digitado (todos os comentários são meus):
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
A saída asm acima era do CLANG, mas todos os outros compiladores que eu analisei deram saída semelhante. Isso é verdadeiro para todos os compiladores nesse site, sejam eles compiladores C ou C ++ puros, todos sem pragmas para alterar o modo do compilador (que por padrão é C ++ para os compiladores C ++)
Observe que seu compilador não definiu i = 1, mas i = TRUE (que significa qualquer valor inteiro de 32 bits e não zero). Isso ocorre porque o operador && avalia apenas se uma instrução é VERDADEIRA ou FALSA e, em seguida, define os resultados de acordo com esse resultado. Como prova, tente alterar i = 1 para i = 2 e observe por si mesmo que nada mudará. Veja você mesmo usando qualquer compilador online no Compiler Explorer
i
está definida como1
.