0

I encountered the below question in a C test:

Do the following two programs have the same output:

Program 1:

#include <stdio.h>

int main(){
    float p[3][2];

    int j=0;

    for(int i=0; i<3; i++){
        printf("Enter x%d y%d :", i+1, i+1);
        scanf("%f %f", &p[i][j], &p[i][++j]);
        j=0;
    }

    printf("%f %f\n", p[0][0], p[0][1]);
    printf("%f %f\n", p[1][0], p[1][1]);
    printf("%f %f", p[2][0], p[2][1]);

    return 0;
}

Program 2:

#include <stdio.h>

int main(){
    float p[3][2];

    for(int i=0; i<3; i++){
        printf("Enter x%d y%d :", i+1, i+1);
        scanf("%f %f", &p[i][0], &p[i][1]);
    }

    printf("%f %f\n", p[0][0], p[0][1]);
    printf("%f %f\n", p[1][0], p[1][1]);
    printf("%f %f", p[2][0], p[2][1]);

    return 0;
}

While writing the test, for obvious reason I reasoned that, In runtime j and j++ (line 10 program 1) will get replaced by 0 and 1, So both programs will have the same output. But when I checked it in my computer output for both programs was as follows:

Output of Program 1:

Enter x1 y1 :1 1
Enter x2 y2 :3 2
Enter x3 y3 :4 1
-0.000000 1.000000
-0.000000 2.000000
0.000000 1.000000

Output of Program 2:

Enter x1 y1 :1 1
Enter x2 y2 :3 2
Enter x3 y3 :4 1
1.000000 1.000000
3.000000 2.000000
4.000000 1.000000

I think, in program 1 the values for p[0][0], p[1][0], p[2][0] are garbage values. I want to know why p[0][0], p[1][0], p[2][0] did'nt received the input values 1, 3, 4 respectively.

Sazzad Hissain Khan
  • 37,929
  • 33
  • 189
  • 256
Hash
  • 556
  • 5
  • 17
  • 1
    `scanf("%f %f", &p[i][j], &p[i][++j]);` attempts to both use **and** update `j` in the same expression (without an intervening *sequence point*). This is **UB** (Undefined Behaviour) – pmg Jan 05 '20 at 14:29
  • 1
    The first one is undefined behavior. You don't know which of the expressions `j` or `++j` will be evaluated first. – HAL9000 Jan 05 '20 at 14:30
  • i dont know the concept of UB please elaborate – Hash Jan 05 '20 at 14:32
  • @HAL9000 it's not so much the expressions themselves but rather the order in which `j` (reading `j`) and the side-effect of `++j` (updating `j`). – pmg Jan 05 '20 at 14:34
  • UB: http://wiki.c2.com/?UndefinedBehavior and many other google hits – pmg Jan 05 '20 at 14:35
  • @pmg, I know there is more going on than the order of evaluation, the read an update may not even be atomic. But there is not need add to the confusion by explaining everything that can go wrong. – HAL9000 Jan 05 '20 at 14:46
  • See also [Undefined, unspecified and implementation-defined behavior](https://stackoverflow.com/q/2397984/15168) – Jonathan Leffler Jan 05 '20 at 16:26

1 Answers1

-1

This is happening because you first increment the value of j and than read it when you use ++j. However if you use j++ you will first read the value and then increment it and the program should work. So the scanf line would look as follow:

scanf("%f %f", &p[i][j], &p[i][j++]);

But be CAREFUL because I don't think that this is consider as good practice and even the compiler throws a warning.

warning: operation on ‘j’ may be undefined [-Wsequence-point]
         scanf("%f %f", &p[i][j], &p[i][j++]);
                                        ~^~
teya
  • 17
  • 2
  • 1
    `++j` is not specified to increment `j` and then read it, nor is `j++` specified to read `j` and then increment it. Rather, `++j` evaluates to `j+1` and as a **side effect** increments `j`. The actual increment may occur before, during, or after the evaluation. Similarly, `j++` evaluates to `j` and as a side effect increments `j`. – Eric Postpischil Jan 05 '20 at 15:17
  • Your first sentence is a bit dubious; your 'however' sentence is just wrong, though. The compiler correctly gives a warning (though you should be using `-Werror` so it becomes an error) — and it would give the same warning on the code in the question. – Jonathan Leffler Jan 05 '20 at 16:23