Different and odd results when using prefix and postfix operators in function arguments

118 views Asked by At

Code:

#include <stdio.h>

int main()
{
    int i = 3;
    printf("%d %d %d %d %d\n",i = 7,--i,i = 18, i+5, i = 0);
    printf("%d %d %d %d %d\n",i = 7,i--,i = 18, i+5, i = 0);

    return 0;
}  

Output:

7 7 7 5 7
7 18 7 5 7

Why I am getting this output, can anyone explain to me how are these expressions inside printf statements are executed?

I mean, in which order are considered by compiler?

3

There are 3 answers

0
molbdnilo On BEST ANSWER

The order of evaluation of arguments is unspecified, and unsequenced modifications to the same object has undefined behaviour.

So, formally, reasoning about your code is meaningless.

However, it is explainable with evaluation from the right, and not irrational or random.
(Note that most of the arguments are the same as passing i; i = 18 "is" i, not 18.)

The first:

i = 0;
int new_variable = i + 5;
i = 18;
i -= 1;
i = 7;
printf("%d %d %d %d %d\n", i, i, i, new_variable, i);

The second:

i = 0;
int new_variable = i + 5;
i = 18;
int previous_i = i;
i = 7;
printf("%d %d %d %d %d\n", i, previous_i, i, new_variable, i);
i -= 1;
1
MrFthiz On

This is a very weird code, and you should never aspire to write code like this, it brings unnecessary confusion.

Function arguments can be evaluated in any order depending on the compiler settings, so the output of this code can vary depending on your compiler and settings.

I'm assuming you saw this code on some school class, this type of examples usually show up when teachers try to explain post-increment and pre-increment.

Please understand pre-increment and post-increment diference fist:

  • ++x (pre-increment) means "increment the variable; the value of the expression is the final value"
  • x++ (post-increment) means "remember the original value, then increment the variable; the value of the expression is the original value"

edit: change the explanation to not cause confusion, the output might vary depending on multiple variables.

0
anastaciu On

The big problem here is that the changes made in i invoke undefined behavior due to the lack of a sequence point.

A program exhibiting undefined behavior imposes no requirements as to how the compilation process should occur, the compiler may deal with it as it sees fit, and different compilers or even different versions of the same compiler will produce different results.

Though it's not required, one thing they usually do is to produce some warning, provided that warning flags are enabled, and some won't even need that, demo.

Relevant standard entry:

N1570 ISO/IEC 9899:201x C11

§6.5 Expressions:

2 - If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings.

To be clear, the comma operator is not a sequence point.

I should also note that the order of evaluation of function arguments is unspecified.

§6.5.2.2 Function calls

10 - There is a sequence point after the evaluations of the function designator and the actual arguments but before the actual call. Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function.

As already pointed out, this is not code you should show anyone, granting that in this case is for learning purposes.