#include <stdio.h>
int main()
{
int i=2;
if(i==3,4)
{
printf("If block");
}
else
{
printf("Else block");
}
return 0;
}
Why is this code returning "If block" ?``
#include <stdio.h>
int main()
{
int i=2;
if(i==3,4)
{
printf("If block");
}
else
{
printf("Else block");
}
return 0;
}
Why is this code returning "If block" ?``
The expression in the if
statement:
(i==3,4)
Contains the comma operator. It evaluates its left operand, discards its value, then evaluated the right operand which is its result. This operator also has lower precedence than the equality operator ==
, so this parses as:
((i==3),4)
So i==3
is first evaluated. Since i
has the value 2 the comparison is false resulting in i==3
evaluating to 0. This value is discarded. Then 4
is evaluated which becomes the value of the entire expression. Since this value is non-zero, the if
block is true, so "If block" is printed.
In the condition of the if statement
if(i==3,4)
there is used the comma operator.
From the C Standard (6.5.17 Comma operator)
2 The left operand of a comma operator is evaluated as a void expression; there is a sequence point between its evaluation and that of the right operand. Then the right operand is evaluated; the result has its type and value
That is the above if statement can be equivalently written like
if( ( i==3 ), ( 4 ))
So according to the quote from the C Standard the left operand ( i == 3 ) is evaluated as a void expression that is its result is discarded. And the result of the whole expression is the value of the right operand that is of the expression ( 4 )
. As this expression is not equal to 0 then the whole condition is evaluated as logical true and the sub-statement of the if statement is executed.
"Why is this code returning "If block" ?``"
The explanation of why the expression if(i==3,4)
causes execution flow to go to the true branch is provided in good detail in the other answers. In short the idea that it evaluates its first operand and discards the result, Then uses the second operand to evaluate as the condition.
But, some might ask is this useful?
One use is to force a side effect prior to deciding which branch to flow to.
For example
if (numeric_read(str, &err), !err)
// ^ ^ result 'err' of side effect used in if evaluation.
^
// causes side effect by call function which assigns value to err.
The side effect here populates err
, then discards the logical result of the call in the first argument. The value assigned to err
is then used to select the branch.