5

How to explain the output of the below code:

include <stdio.h>

int main(void) {
    int k;
    printf("%d %d\n",k=1,k=3);
    return 0;
}

Ideone Link

My thinking was that 1 will be assigned to k variable and then 1 would be printed. Similarly 3 will be assigned to k and output will be 3.

Expected Output

1 3

Actual Output

1 1

I am extrapolating from

int a;
if (a = 3) { 
    ...
} 

is equal to

if (3) { 
    ... 
}

Please let me know where am I going wrong?

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
jayd
  • 59
  • 1

2 Answers2

7

The problem is, the order of evaluation of function arguments are not defined, and there's no sequence point between the evaluation or arguments. So, this statement

 printf("%d %d\n",k=1,k=3)

invokes undefined behavior, as you're trying to modify the same variable more than once without a sequence point in between.

Once a program invoking UB is run and (if) there's an output, it cannot be justified anyway, the output can be anything.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
-4

I expect the reason you're seeing 1 1 is because the two assignment statements are happening control is passed to printf.

printf("%d %d\n",k=1,k=3);

So in response to the down-votes, yes, this this is undefined behavior, and therefore you shouldn't count on this behavior continuing. However, in terms of identifying why the output was 1 1 and not 1 3, we could infer that the assignment of 3 may have been stomped on by a subsequent assignment of 1.

When printf is invoked, the call stack contains two entries containing the final value of k, which is 1.

You can test this out by replacing those with a function that prints something when it executes.

Sample Code:

#include <stdio.h>

int test(int n) {
    printf("Test(%d)\n", n);
    return n;
}

int main(void) {
    int k;
    printf("%d %d\n",k=test(1), k=test(3));
    return 0;
}

Output:

Test(3)
Test(1)
1 1
Scovetta
  • 3,112
  • 1
  • 14
  • 13
  • This is a poor explanation at a likely much more contrived reason – q.Then Feb 20 '17 at 06:52
  • 1
    @q.Then Poor is a mild word, this is wrong. – Sourav Ghosh Feb 20 '17 at 06:52
  • I'm genuinely curious as to how my explanation is wrong. Is the argument just that multiple assignment is UB? – Scovetta Feb 20 '17 at 07:07
  • `I expect the reason you're seeing 1 1 is because`...there's no universal reason. so any one reason , mentioned is wrong. An answer, if any, will be very very platform and environment specific. – Sourav Ghosh Feb 20 '17 at 07:08
  • @SouravGhosh: Yes, the behavior is undefined, but there's nothing wrong with speculating about what it does. – Keith Thompson Feb 20 '17 at 07:38
  • @KeithThompson Very correct sir, but the problem is, without an explicit mention to those aspects, someone without proper insights coming accross the answer will come up with a question like, why in my case it is "3 3"? The same as the one case printf evaluates arguments right to left and something....without specific context, that is not guaranteed, right? – Sourav Ghosh Feb 20 '17 at 07:50
  • @SouravGhosh: The answer acknowledges that the behavior is undefined. – Keith Thompson Feb 20 '17 at 08:02
  • 1
    In all fairness, I don't think I explicitly mentioned UB in the initial answer. The intent was speculating on what the poster's compiler actually did, rather than what the language spec requires/allows, but I should have been more explicit. – Scovetta Feb 20 '17 at 08:10