-1

There are 3 loops, which last loop does not behave as expected. Loop #2 and loop #3 are bad code styling. They are here just for demonstration. Question is why printf() in loop #3 gives unexpected output and printf() in loop#2 gives expected result?? Is this error because compiler or because printf function? Is there any documents which explain how compiler or some function behave in certain situation so I can look for future issues.

int main(void) {

int mat1[3][4] = {4,5,0,3,0,0,1,2,0,0,0,6};

//****************** Output 1 ***********************************************

    for(int i=0; i<3;i++)
        for(int j=0;j<4;j++){
            printf("%d, ", mat1[i][j]);
            if(j==3)printf("\n");
        }


    /*   Expected output 1:

        4 5 0 3 
        0 0 1 2 
        0 0 0 6
    */

    printf("\n\n");

//******************* Output 2 ************************************************ 

    for(int i=0; i<3;i++)
        for(int j=0;j<4;j+=4)

            printf("\n%d, %d, %d, %d", mat1[i][j+0],mat1[i][j+1],mat1[i][j+2],mat1[i][j+3]);



    /*  Expected output 2:

        4 5 0 3 
        0 0 1 2 
        0 0 0 6
    */

    printf("\n\n");

//********************* Output 3 **********************************************

    for(int i=0; i<3;i++)
        for(int j=0;j<4;j)

            printf("\n%d, %d, %d, %d", mat1[i][j++],mat1[i][j++],mat1[i][j++],mat1[i][j++]);


    /*  Unexpected output 3:

        3 0 5 4 
        2 1 0 0 
        6 0 0 0
    */

}
Zeljko M
  • 1
  • 2
  • 5
    Using `j++` in multiple arguments to the same function call produces undefined behavior. – Barmar Jul 23 '18 at 21:57
  • 1
    What's the point of the inner `for` loop in #2? It will only execute once because `j += 4` immediately reaches the end. – Barmar Jul 23 '18 at 21:58
  • Which `printf` is giving unexpected results? – Barmar Jul 23 '18 at 22:00
  • The point of the loop #2 is just for demonstration. Even it is bed code practice, it work properly. Loop #3 is confusing. – Zeljko M Jul 23 '18 at 22:13

1 Answers1

0
    printf("\n%d, %d, %d, %d", mat1[i][j++],mat1[i][j++],mat1[i][j++],mat1[i][j++]);

That is very bad coding style, but what is happening is printf is evaluating j from right to left before it prints them out. So that's why at the first mat1[i][j++] j is going to be 3, at the second 2 and so on untill the last mat1[i][j++] will have a j which will be 0.

Leon Trotsky
  • 250
  • 1
  • 10
  • 3
    The order of evaluation of arguments is not defined, which is the rationale for this causing undefined behavior. – Barmar Jul 23 '18 at 21:59
  • You are right, it is not. But this is what happens most of the time in cases like this. – Leon Trotsky Jul 23 '18 at 22:02
  • 2
    My point is that they shouldn't count on any specific order, left-to-right or right-to-left. – Barmar Jul 23 '18 at 22:04
  • Loop#2 and loop#3 are bad coding style, there are here only for demonstration. I understand what heppening in loop#3 but not why. Why loop#2 than gives good result. Why printf in loop#2 is evaluating from left to right and printf in loop#3 is evaluating from right to left.?? – Zeljko M Jul 23 '18 at 22:19
  • Like Barmar said on loop3 it is undefined behaviour, but in your case i explained what is happening. On loop2 on the other hand there is a major difference: j+1 and j++ are not the same. j+1 does nothing to the variable, j remains unchanged, so it doesn't matter in what order the function is doing evaluations, on the other hand j++ is actually j=j+1, so j will change its value. – Leon Trotsky Jul 23 '18 at 22:22
  • So as I understand in loop #2 compiler just substitute j+1 with right result befor printf function start to execute. In loop #3 j++ determinate during execution of printf function which can lead to bad result. So in this exemple we can see that printf function start to fill arguments from right to left side and because that is not clever to have side efects of computation in printf function ( or any function). Thank you!! – Zeljko M Jul 23 '18 at 22:41
  • `printf` doesn't evaluate `j` . A function's arguments are evaluated before the function is called. – M.M Jul 23 '18 at 22:49
  • @ZeljkoM It's the side effects that cause the problem. They tip the code from merely confusing, to undefined. And it's not all side effects that are bad: it's when you have(a) multiple side effects, or (b) side effects affecting variables which are used elsewhere. An example of (a) is `printf("%d %d", j++. j++)`. An example of (b) is `printf("%d %d", j, j++)`. Both of those are undefined, as are versions where `j` or `j++` are used as subscripts. But (c) `printf(%d", j++)` is perfectly fine, because the side effect is isolated. `printf(%d", mat[I][j++])` would be fine, too. – Steve Summit Jul 23 '18 at 22:55