-1

Why does the following code produces this output:

Code Snippet:

int a=10;
printf("%d%d%d",++a,a++,++a);

Output:

131113

How are are parameters evaluated? Does this depend upon compiler? I use gcc compiler. Can anybody tell me how my compiler evaluated it? If the compiler evaluates parameters of a function from Right to Left then will the output of this code be the following:

121111
user221458
  • 716
  • 2
  • 7
  • 17
  • 1
    Undefined behavior. You can count on `++a` incrementing before an expression is evaluated, or `a++` after, but you cannot count on the order in which actions are taken within the same sequence point. – DavidO Oct 03 '13 at 07:28
  • 1
    It does depend on the compiler. There's no guarantee that any two compilations will have the same order, even. – Gabe Oct 03 '13 at 07:30
  • 1
    Correct: it is implementation dependent, but the behavior is not defined in the standard, nor can it be relied upon to not change in future versions of the same compiler, or even under different barometric pressures. ;) – DavidO Oct 03 '13 at 07:31
  • I am getting the same result on gcc regardless of how many times I compile it. Assuming the compiler will evaluate the parameters from Right to Left then what will be the answer? – user221458 Oct 03 '13 at 07:31
  • 1
    `Assuming the compiler will evaluate the parameters from Right to Left` - you are not allowed to assuming that. – Sadique Oct 03 '13 at 07:31
  • 1
    If you assume anything other than "this is garbage", you lose. – DavidO Oct 03 '13 at 07:32
  • 1
    This is UB: the compiler can do what it wants; including reformatting your hard disk. – Bathsheba Oct 03 '13 at 07:32
  • 1
    The most likely thing that it will do is behave differently the day you go to production. – DavidO Oct 03 '13 at 07:33

2 Answers2

2

That is Undefined Behavior. Modifying a variable more than once in a sequence point is Undefined Behavior.

From Wiki:

A sequence point defines any point in a computer program's execution at which it is guaranteed that all side effects of previous evaluations will have been performed, and no side effects from subsequent evaluations have yet been performed.

Please read: Operator Precedence vs Order of Evaluation

For a thorough understanding please read: Undefined Behavior and Sequence Points

You can do this though:

int a=10;
int b = (++a,a++,++a);

Because the Comma (,) is an operator here and not just a mere separator between the arguments as in case of printf.

Community
  • 1
  • 1
Sadique
  • 22,572
  • 7
  • 65
  • 91
1

This is actually a combination of both unspecified behavior and undefined behavior.

It is unspecified because the order of evaluation of function arguments is not specified so in this line:

printf("%d%d%d",++a,a++,++a);
       ^        ^   ^   ^
       1        2   3   4

we do not know which order functions arguments 1 to 4 will be evaluated and it is even possible that if this was in a loop that on subsequent executions the order could be different. This is covered in the C99 draft standard section 6.5.2.2 Function calls paragraph 10 which says(emphasis mine):

The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call.

By itself this means the output of the program is unreliable but we also have undefined behavior due to the fact that the code above modifies a multiple times within one sequence point. This is covered by section 6.5 Expressions paragraph 2 which says(emphasis mine):

Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression.72) Furthermore, the prior value shall be read only to determine the value to be stored.73)

Undefined behavior means that anything could result from running this program including that it appears to work correctly, the term is defined in section 3.4.3 and includes the following note which explains the possible result of undefined behavior:

Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).

Beyond that even if you could obtain reliable results code like that is hard to read and would be a nightmare to maintain in a complex project. If there are alternative simpler ways to write the code that meets other requirements such as performance etc... then that is the approach you should take.

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740