-1

I am not getting expected output in the following C code

main(){
    int i=0,j=-2,k=0,m;

    if((!i||--j&&k++)&&(i++||j++&&!k++))
    {
        printf("i=%d j=%d k=%d",i,j,k);

    }
    return 0;
}

I got the output in compiler as :

i=1 j=-1 k=1

But I don't understand what exactly is going on here.

I think the if statement should not run since its argument is false

Note the first bracket (!i||--j&&k++)

here as !i=1 hence this bracket is true since anything with 1 under OR operator will be true.

out values become: i=0, j=-3, k=1

Now notice the second bracket: (i++||j++&&!k++)

Here we have ( 0 || -3 && !1) = 0, false

as the brackets are separated by &&, the whole argument of if statement becomes false.

Please explain me where my argument is wrong. I am a new to C

dbush
  • 205,898
  • 23
  • 218
  • 273
chesslad
  • 171
  • 7
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/198974/discussion-on-question-by-abhay-not-getting-expected-output-from-this-code-using). – Samuel Liew Sep 04 '19 at 23:54

3 Answers3

6

The logical AND operator && and the logical OR operator || are short circuit operators, meaning that the right side won't be evaluated if the result of the expression can be determined from the left side.

So when this subexpression runs:

(!i||--j&&k++) 

Which is parsed as:

(!i||(--j&&k++)) 

The left side of the || evaluates to true, so --j&&k++ is not evaluated, meaning the value of j remains -2 and the value of k remains 0.

So the left side of the outermost && is true, so now we evaluate the right side:

(i++||j++&&!k++)

Which is parsed as:

(i++||(j++&&!k++))

i is incremented to 1, then the old value is used in ||. The old value of 0 evaluates to false so the right side is evaluated. j is incremented to -1 and the old value of -2 evaluates to true, so the right side of && is evaluated. k is incremented to 1 and the old value of 0 is applied to the ! operator which evaluates to true. This makes the entire expression true and the statement is printed, at which time i is 1, j is -1, and k is 1.

dbush
  • 205,898
  • 23
  • 218
  • 273
5

Let’s spread this out a little to make reading it easier:

int i = 0, j = -2, k=0, m;

(!i || --j && k++) && (i++ || j++ && !k++)

As you note !i is true (value 1), so the || is true. The || operator is defined not to evaluate its right operand if the left operand is true, so --j && k++ is not evaluated and has no effect. (The right operand is --j && k++ because && has higher precedence than ||, so A || B && C is structured as A || (B && C).)

That settles the left operand of the central &&. In the right operand, i++ increments i to 1 but evaluates to the current value of i, 0, so it is false for the purposes of the || operator. So the right operand of that || is evaluated.

That operand is j++ && !k++. Since j is −2, j++ changes j to −1 and evaluates to −2, which is a value of true for the purposes of &&. Then k++ increments k to 1 but evaluates to 0, and !k++ changes this to 1, yielding true for the && and therefore true for the previous || and the central &&.

At this point i is 1, j is −1, and k is 1, which is the result you got.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
1

you may be missing that if statements ends once they are satisfied, so (!i||--j&&k++) is only going to compute i and the other operations are going to be disregarded. By that I mean j is going to be -2 by the end of the first statement.

ignacio
  • 1,181
  • 2
  • 15
  • 28
  • Thanks a lot for clearing that. I had a feeling that this is what was happening here but had to post here to be sure. Thanks a lot – chesslad Sep 04 '19 at 20:47
  • I would recommend the "fail fast" approach. Try creating a simple file and printing their values for smaller if statements. – ignacio Sep 04 '19 at 20:50