-2
int inp, temp;

inp = 2347653;

printf("%d, %d", (temp = inp / 10000, inp %= 10000, temp), (temp = inp / 1000, inp %= 1000, temp));

this program showed me an unexpected result. ( 0, 0 )

So I tried separate the program like this

printf("%d, ", (temp = inp / 10000, inp %= 10000, temp));

printf("%d", (temp = inp / 1000, inp %= 1000, temp))

it works properly. Therefore, I thought there is an operator issue. I think the comma between two expressions didn't work as a punctuation but an operator. What should I do to make the first program work? and Why the compiler comprehend the comma as an operator?

  • 3
    Does this answer your question? [What does the comma operator , do?](https://stackoverflow.com/questions/52550/what-does-the-comma-operator-do) – Mark Benningfield Dec 12 '22 at 11:14
  • Are you confusing formatting (anything between `""` is an arbitrary string and can contain whatever punctuation you want) with syntax (everything outside the `""` is C and every character is always understood as C syntax)? – Useless Dec 12 '22 at 11:22
  • 1
    "showed me an unexpected result." What result do you get, what did you expect and why? – Gerhardh Dec 12 '22 at 11:36
  • @MarkBenningfield This question is about order of evaluation of function arguments, more so than the behavior of the comma operator. Not a duplicate to that link. – Lundin Dec 12 '22 at 13:34

2 Answers2

1

You are mixing 2 different uses of the comma lexical element.

  1. It can be used as an operator between 2 expressions. In that case both expressions are evaluated in order, and the result of the operator is the result of the second expression. Or
  2. It can be used to separate the parameters in a function call. In that case all the parameters are evaluated in a non specified order, and the function call is evaluated after all its parameter have been evaluated.

In your first version of code, you call the print function with 3 parameters (format string and 2 arguments), and the compiler is free to evaluate the parameters in any order. In the second version, you have 2 distinct calls and the compiler has to fully evaluate first call before starting the evaluation of the second (or at least the result must be what they should be if the rule had been obeyed...)

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • 3
    If the arguments (not parameters) to a function were evaluated in “a non specified order,” that would mean there is some order to their evaluation, but it is not specified. However, evaluation of function arguments is unsequenced. They not only can be evaluated in any order but their evaluations can be intermingled, with multiple parts of different arguments being interleaved. If the arguments were evaluated in an unspecified order, then `printf("%d %d\n", x++, x++);` would have not undefined behavior, since the `x++` would be indeterminately sequenced, not unsequenced. – Eric Postpischil Dec 12 '22 at 12:02
  • Specifically there are side effect on `temp` which are not sequenced in relation to a value computation of `temp`, meaning UB. The comma operator guarantees sequence points between its operands but it does not have a sequence point before or after it. – Lundin Dec 12 '22 at 13:48
  • https://godbolt.org/z/EEoj6YMa6 This example should remove the UB but leave the unspecified behavior. So it can print either `0, 2347` or `237, 7` but it will not go haywire like the OP's code. Compare gcc vs clang on x86 in the godbolt link for example. – Lundin Dec 12 '22 at 14:10
1

Why the compiler comprehend the comma as an operator?

Because it can be an operator. What does the comma operator , do? In your case you have the argument list to printf separated by commas - those are not operators as such but part of the function call syntax. But the commas inside each parenthesis is the comma operator.

this program showed me an unexpected result.

There is no expected result - you are invoking both undefined and unspecified behavior.

Each sub-expression (temp = inp / ..., inp %= ..., temp) is sequenced from left to right, as guaranteed by the comma operator. But the two sub-expressions aren't sequenced in relation to each other: the order of evaluation of function arguments is unspecified.

Furthermore, there is no sequence point between the temp = inp... expression of each subexpression and the right-most value computation of temp in the other expression, meaning that the code invokes undefined behavior. And that's why your second example works, it has the poorly-defined behavior removed.

Do not mix over ten(!) operators and four(!) side-effects in the same expression. That's plain obfuscation. Instead rewrite it as readable, well-defined C:

int inp, result1, result2;

inp = 2347653;

result1 = inp / 10000;
inp %= 10000;
result2 = inp / 1000;
inp %= 1000;

printf("%d, %d", result1, result2);
Lundin
  • 195,001
  • 40
  • 254
  • 396