0

I have seen in this site that prefix increment or postfix increment in a function call may cause undefined behavior. I have gone through one of those recently. The source code is something like this :

#include <stdio.h>

void call(int,int,int);
int main()
{
    int a=10;
    call(a,a++,++a);
    printf("****%d %d %d***_\n",a,a++,++a);
    return 0;
}

void call(int x,int y,int z)
{
    printf("%d %d %d",x,y,z);
}

The output comes out as 12 11 12****14 13 14***_. But, when a is printed first in the function, shouldn't it be 10? Why does it become 12? Also, why does a++ decrease from 12 to 11? Can someone please kindly explain? Thank you.

Ishrak
  • 509
  • 1
  • 9
  • 17
  • 1
    That's the "Undefined Behavior" part. See also http://stackoverflow.com/questions/2989704/order-of-operations-for-pre-increment-and-post-increment-in-a-function-argument?rq=1 – Jongware Apr 29 '14 at 15:13

4 Answers4

2

There are two things your example code requires us to consider:

  1. The function arguments order of evaluation is unspecified. Therefore, either ++a or a++ is evaluated first but it is implementation-dependent.

  2. Modifying the value of a more than once without a sequence point in between the modifications is also undefined behavior.

Because of point 2, you have double undefined behavior here (you do it twice). Note undefined behavior doesn't mean nothing happens; it means anything can happen.

call(a,a++,++a); /* UB 1 */
printf("****%d %d %d***_\n",a,a++,++a); /* UB 2 */
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
1

That is undefined behaviour and as such it is entirely up to the implementation of the compiler in which order the following operations are done:

  1. submit argument a
  2. submit argument a++
  3. submit argument ++a
  4. increment a for ++a
  5. increment a for a++

The only thing that the compiler knows is: 2. has to happen before 5. and 4. has to happen before 3.

You are observing:

++a;
submit argument 2
a++;
submit the other arguments
Sergey L.
  • 21,822
  • 5
  • 49
  • 75
  • 2
    We have **Undefined Behavior** here, not **Unspecified Behavior** or **Implementation-defined Behavior**. This is just ***wrong***. – Deduplicator Apr 29 '14 at 15:21
  • 2
    UB does not mean that the possible outcome is in any way bounded by naive reordering of the written sub-operations. It is completely undefined. – Deduplicator Apr 29 '14 at 15:29
  • Let's assume that we are having an undefined behavior. But, every time, it seems that, a gets incremented up to ++a through a++ which makes 10 to become 12. But, a++ already had 11 in it. And, ++a had 12 in it. So, 12 11 12 is printed. @Deduplicator, why do we call it UB even after it follows a specific sequence everytime? – Ishrak Apr 30 '14 at 05:38
  • @hayet: It is called that because the specification allows anything to happen: [Anything at all.](http://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior) The fact that your implementation with your optimisation settings in your environment in all instances you checked always acted the same way does not change anything, at most giving you a treacherous feeling of unjustified complacency. – Deduplicator Apr 30 '14 at 09:11
  • #Deduplicator, that clarifies the undefined behavior. – Ishrak Apr 30 '14 at 18:32
0

The C and C++ standards do not indicate an order of evaluation for function arguments. To be blunt, it is not incorrect for a compiler to cause the parameters to be evaluated from right to left, or left to right.

The best answer is, Stay Away from this type of 'Undefined Behavior'; as it can lead to subtle portability problems.

Mahonri Moriancumer
  • 5,993
  • 2
  • 18
  • 28
-1

There's no requirement that a be equal to anything; that's what is meant by undefined behavior. It's entirely up to the compiler to evaluate the arguments to call and to printf in any order it sees fit, because the language does not specify what order they need to be evaluated.

chepner
  • 497,756
  • 71
  • 530
  • 681
  • 3
    Implementation-defined and Unspecified behavior are not Undefined Behavior. – Deduplicator Apr 29 '14 at 15:20
  • 1
    Please provide an example where the language makes a distinction. – chepner Apr 29 '14 at 15:33
  • Chapter `3 Terms, Definitions and Symbols` gives the definitions for all three types of behavior. An example for UB: `++x+x++`, and example of ID: `sizeof(int)`. An example of unspecified behavior: "An example of unspecified behavior is the order in which the arguments to a function are evaluated." – Deduplicator Apr 29 '14 at 15:41
  • Thank you; that clarifies the issue. – chepner Apr 29 '14 at 15:45