9
main()
{
    int i=5;
    printf("%d%d%d%d%d%d",i++,i--,++i,--i,i);
}

Output is 45545, but I don't how it is working. Some say that the arguments in a function call are pushed into the stack from left to right.

Cœur
  • 37,241
  • 25
  • 195
  • 267
java
  • 1,124
  • 2
  • 14
  • 33

5 Answers5

21

The evaluation order of function parameters is unspecified.

From c99 standard:

6.5.2.2 Function calls

10/ 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.

This is, however, only a part of the problem. Another thing (which is actually worse, since it involves undefined behavior) is:

6.5 Expressions

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

In our case all the arguments evaluation is between only 2 sequence points: the previous ; and the point before the function is entered but after all the arguments have been evaluated. You'd better not write a code like this.

C standard is pretty relaxed in some places to leave room for optimizations that compilers might do.

Maksim Skurydzin
  • 10,301
  • 8
  • 40
  • 53
6

The order in which the parameters to a function are passed is not defined in the standard, and is determined by the calling convention used by the compiler. I think in your case, cdecl calling convention (which many C compilers use for x86 architecture) is used in which arguments in a function get evaluated from right to left.

ale10ander
  • 942
  • 5
  • 22
  • 42
Raj
  • 4,342
  • 9
  • 40
  • 45
  • 2
    This should also mention that the code has *undefined behaviour*. Someone who quickly scans this Q/A without revising the other answers might overlook that fact and assume the behaviour in the question is reliable for cdecl calls. – M.M Jul 23 '18 at 23:26
  • The question is about *order of evaluation* (which is **unspecified**), not about how parameters are passed (after their evaluation). – Toby Speight Aug 28 '18 at 12:25
3

Two points:

  • Function arguments are evaluated in an unspecified order. This allows the compiler to optimize however it likes.
  • Your particular arguments invoke undefined behavior. You're not allowed to modify i multiple times before a sequence point.
M.M
  • 138,810
  • 21
  • 208
  • 365
Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
  • 1
    *You're not allowed to modify i multiple times in a single statement.* This is not true: for example: `i++, i++;` is a single statement and you are modifying an object twice but it is not UB. – ouah Oct 18 '12 at 18:01
  • What is the better term for this? I don't think expression fits either. I've switched to sequence point, but I don't really like the wording now. – Bill Lynch Oct 18 '12 at 18:07
  • *sequence point* is the right wording. – ouah Oct 18 '12 at 18:09
3

This function call is undefined behavior:

printf("%d%d%d%d%d%d",i++,i--,++i,--i,i);

Modifying an object more than once between two sequence points is undefined behavior in C.

It is also undefined behavior because you have 6 conversion specifications but only 5 arguments for the format.

ouah
  • 142,963
  • 15
  • 272
  • 331
  • As comment length is limited i have rephrased the statement as printf("%d %d %d %d",i,++i, i++,i); with i=1 During evaluation, first it will take all the values starting from right into the stack. If the variable has any post/pre increment, it evaluates and stores the value. Else, it stores as a variable in the stack and takes the final value of the var. right most i - i in to the stack, for i++ - 1 because its post inc updates i as 2. for ++i - 3, pre inc and updates i as 3 for i as it is in the stack. for var as i in stack takes final value of i as 3. Final output will be 3 3 1 3 – Dinesh Jan 19 '18 at 15:48
  • 1
    @Dinesh Thanks for the downvote but as others already told you, you are wrong. There is no "stack" in C Standard but there is a concept of *sequence points* with related requirements. – ouah Jan 20 '18 at 16:37
1

The evaluation order of printf arguments is unspecified. It depends, among other, on the calling convention of the system you are using. Moreover, this is also an undefined behavior, because you are modifying i several times without any sequence point. BTW, there is a missing argument.

md5
  • 23,373
  • 3
  • 44
  • 93