Search code examples
clogical-operatorspostfix-operatorprefix-operator

how to solve the postfix and prefix operator expression?


I wrote the following code:

int main(){

int i=-1,j=-1,k=0,l=2,m;
m = i++ && j++ && k++ || l++;
printf("%d %d %d %d %d",i,j,k,l,m);

i=-1,j=-1,k=0,l=2,m;
m = ++i && ++j && ++k || ++l;
printf("\n%d %d %d %d %d",i,j,k,l,m);
    return(0);
}

and i got the following result:

    0 0 1 3 1

    0 -1 0 3 1

as i know postfix and prefix operators are solved after the semicolon,ie. the original values are used in the expression and then the variables resolve themselves. In that case

     i++ && j++ 

should be equal to

      ++i && ++j 

and both should be equivalent to

     i && j;
     i = i+1;
     j = j+1;

and hence the result for the two expressions must be same. but it is not so. please anyone can help me with where do i have a wrong concept.


Solution

  • i++ && j++ is definitely not equivalent to ++i && ++j.

    Take the case where both are zero - the first results in:

    0 && j++
    

    yielding a 0 result (and because of short-circuiting, j won't even get incremented).

    In the second case, you'll get

    1 && 1
    

    yielding a 1 result.

    With that in mind, let's look at your examples (spaces, semicolons and newlines added for readability):

    1. First up:

      int i = -1;
      int j = -1;
      int k =  0;
      int l =  2;
      int m = i++ && j++ && k++ || l++;
      

      Let's first parenthesize completely to make it easier to deal with:

      int m = ((i++ && j++) && k++) || l++;
      

      So, what's going to happen? First, the i++. i is incremented (and becomes 0), but because it's a post-increment, the expression's result is -1. That gives:

      int m = ((-1 && j++) && k++) || l++;
      

      Since the left side of that && is non-zero, the right side is evaluated. j++ increments j to 0, but again, post-increment means the expression's value is -1.

      int m = ((-1 && -1) && k++) || l++;
      

      Resolve that &&:

      int m = (1 && k++) || l++;
      

      Next, the right side of the remaining &&. k is incremented, becoming 1, but the expression yields 0:

      int m = (1 && 0) || l++;
      

      Resolve this &&:

      int m = 0 || l++;
      

      And finally, because the left side of the || is 0, the right side is evaluted. l is incremented, becoming 3, but as a post-increment, yields 2:

      int m = 0 || 3;
      

      Finally:

      int m = 1;
      

      And along the way we ended up with:

      i = 0;
      j = 0;
      k = 1;
      l = 3;
      

      Explaining your first printout.

    2. Next, let's look at the second example (more condensed; let me know if you want more details):

      int i = -1, j = -1, k = 0, l = 2, m;
      m = ((++i && ++j) && ++k) || ++l;   // parenthesized for readability
             ^                            // i is pre-incremented
      m = (( 0  && ++j) && ++k) || ++l;
                 ^                        // first && operator short-circuits
      m = (0 && ++k) || ++l;
              ^                           // second && operator short-circuits
      m = 0 || ++l;
                ^                         // l is pre-incremented
      m = 0 || 3;
             ^                            // evaluate || operator
      m = 1;
      

      The results are:

      i =  0
      j = -1
      k =  0
      l =  3
      m =  1
      

      Exactly what you saw printed out.