incDecUndefined.c

incDecUndefined.c

The question: if x=8

y=x++ - --x + ++x - x--

what is the value of y?

In C board forum, when this question was posted, there were two immediate answers:
1)There is no way to properly solve your equation because it is invoking undefined behavior. You can’t increment or decrement the same variable in the same sequence point.
2)if i write –x then first the deduction is done and then the program goes on.If i write x++ the program goes on and then adds.
So y has the value zero.
Because the above equality is equivalent to words like this
y =
x++ —> set y equal to x and then increase x by one (so y is now 8 and x 9)
– –x —> now first decrease value of x by one and then deduct from y( so y is set to zero and x to 8)
+ ++x —> now first increase value of x by one and then add it to y(so y is set to 9 and x to 9)
– x– —> now first deduct x from y and then decrease value of x by one(so y is set to 0 and x to 8)
Another interesting example i think is this :

int f(int x)
{
      printf("x = %d\n",x);
}
int main(void)
{
     int x=8;
     f(x++);
     f(++x);
     f(x--);
     printf("x = %d\n",x);
     return 0;
}

The evaluation of these answers is as follows:
1)True.
2)False. The example however is well – defined (You achieve consistency by introducing a whole load of sequence points ( all those ; ). Since you are only modifying each variable only ONCE between sequence points, your example is well-defined. (Salem said) Moreover, he said:”L->R evaluation is not guaranteed, specified or assumed at any point.” and he proved it.). By the way, answer number two was mine.

In a relevant question asked on this code

#include <stdio.h>
#define max 52
main(){
    int a=10,b,c,d,e,f,g;
    printf("%d %d %d\n",a,a++,++a);
    a=1;
    b = ++a + ++a + ++a;
    a=1;
    c = ++a + ++a + --a;
    a=1;
    d = --a + ++a + ++a;
    a=1;
    e = ++a + --a + ++a;
    f=max+max;
    g=++max;
    printf("%d\n",b);
    printf("%d\n",c);
    printf("%d\n",d);
    printf("%d\n",e);
    printf("%d\n",f);
    printf("%d\n",g);
    getchar();
     
    /* This prints
       12 11 11
       10
       8
       4
       4 
           104          */
}

The previous question was posted at 07-04-2012. This one on 22-03-2013. Now, the first immediate question was this:
UNDEFINED BEHAVIOR. That time, it came from me, thus proving that I really learnt what the guys told me almost a year before.

AndiPersti tried to compile this code and the compiler speaks for himself – this is not rare for a compiler to do😉 –

$ make foo
cc -Wall -Wextra -ggdb3    foo.c   -o foo
foo.c:3:1: warning: return type defaults to ‘int’ [-Wreturn-type]
foo.c: In function ‘main’:
foo.c:5:31: warning: operation on ‘a’ may be undefined [-Wsequence-point]
foo.c:5:31: warning: operation on ‘a’ may be undefined [-Wsequence-point]
foo.c:7:15: warning: operation on ‘a’ may be undefined [-Wsequence-point]
foo.c:7:15: warning: operation on ‘a’ may be undefined [-Wsequence-point]
foo.c:9:15: warning: operation on ‘a’ may be undefined [-Wsequence-point]
foo.c:9:15: warning: operation on ‘a’ may be undefined [-Wsequence-point]
foo.c:11:15: warning: operation on ‘a’ may be undefined [-Wsequence-point]
foo.c:11:15: warning: operation on ‘a’ may be undefined [-Wsequence-point]
foo.c:13:15: warning: operation on ‘a’ may be undefined [-Wsequence-point]
foo.c:13:15: warning: operation on ‘a’ may be undefined [-Wsequence-point]
foo.c:15:7: error: lvalue required as increment operand
foo.c:23:1: warning: control reaches end of non-void function [-Wreturn-type]
make: *** [foo] Error 1
$ clang foo.c
foo.c:3:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
main(){
^~~~
foo.c:15:7: error: expression is not assignable
    g=++max;
      ^ ~~~
1 warning and 1 error generated.

You see the error is that max is defined and the code tries to modify it. “(by attempting to increment a literal value, which is not permitted) causes a compilation error.”, grumpy nicely said. Without this, the code would run, but running code with warnings is not a good idea. Personally, almost always I treat warnings with the same (or often greater) cautious than errors.

Salem, a great member of my favorite forum, made an interesting post. Here it goes:

– Changing compiler options changes things.
– Changing compiler changes things.
– Even changing the compiler version changes things!.
In short – “DON’T GO THERE!”

This is a catalogue of some experiments showing unspecified behaviour and undefined behaviour.

This was inspired by yet another long bout of explanation in a recent thread, so I thought it was time to dust off a bunch of compilers, and compare.

This is the test code.

#include <stdio.h>

int f1 ( void ) {
  printf( "f1 called = 1\n" );
  return 1;
}
int f2 ( void ) {
  printf( "f2 called = 2\n" );
  return 2;
}
int f3 ( void ) {
  printf( "f3 called = 3\n" );
  return 3;
}
int f4 ( void ) {
  printf( "f4 called = 4\n" );
  return 4;
}
int f5 ( void ) {
  printf( "f5 called = 5\n" );
  return 5;
}

/* Although * happens before +, there is NO guarantee that */
/* f1() will always be called after f2() and f3() */
/* http://c-faq.com/expr/precvsooe.html */
void test1 ( void ) {
  int result;
  printf( "Precedence is not the same as sub-exp<b></b>ression evaluation order\n" );
  result = f1() + f2() * f3() - f4() / f5();
  printf( "Result=%d\n", result );
  printf( "inline=%d\n", f1() + f2() * f3() - f4() / f5() );
}

/* The nature of 'before' and 'after' is poorly understood */
/* http://c-faq.com/expr/evalorder2.html */
void test2 ( void ) {
  int i = 3, j = 3;
  int r1 = ++i * i++;
  printf( "Multiple side effects are undefined\n" );
  printf( "R1=%d, i=%d\n", r1, i );
  printf( "R2=%d, j=%d\n", ++j * j++, j );
}

int main ( ) {
  test1();
  test2();
  return 0;
}

test1() gives a well-defined answer, as one would expect.
What is unspecified however, is the order in which f1() to f5() are called.
That is, the order of the printf statements varies (quite amazingly).

test2() is just broken code with no redeeming features. Yet despite this, people often claim they know how the result is worked out.
One set of results will however make you think about it!

All tests were done using XP as the host OS, with the exception of the gcc test, which was done under Ubuntu.

The only compiler flags used were to test the effect of optimisation.
For most of the Windows compilers, this is basically a choice between “optimise for space” or “optimise for speed”.

The compiler results are presented in approximately alphabetical order.

Borland C++ Compiler 5.5, With Command Line Tools, Version 5.5.1
No Optimisation

Precedence is not the same as sub-exp<b></b>ression evaluation order
f2 called = 2
f3 called = 3
f1 called = 1
f4 called = 4
f5 called = 5
Result=7
f2 called = 2
f3 called = 3
f1 called = 1
f4 called = 4
f5 called = 5
inline=7
Multiple side effects are undefined
R1=16, i=5
R2=16, j=3

Optimisation level O1

Precedence is not the same as sub-exp<b></b>ression evaluation order
f2 called = 2
f3 called = 3
f1 called = 1
f4 called = 4
f5 called = 5
Result=7
f2 called = 2
f3 called = 3
f1 called = 1
f4 called = 4
f5 called = 5
inline=7
Multiple side effects are undefined
R1=16, i=5
R2=16, j=3

Optimisation level O2

Precedence is not the same as sub-exp<b></b>ression evaluation order
f2 called = 2
f3 called = 3
f1 called = 1
f4 called = 4
f5 called = 5
Result=7
f2 called = 2
f3 called = 3
f1 called = 1
f4 called = 4
f5 called = 5
inline=7
Multiple side effects are undefined
R1=16, i=5
R2=16, j=3

Not a lot of surprises here. The result is consistent across all three compilations and the function call order reflects what one would expect from looking at the code.

Digital Mars Compiler Version 8.42n
No Optimisation

Precedence is not the same as sub-exp<b></b>ression evaluation order
f1 called = 1
f2 called = 2
f3 called = 3
f4 called = 4
f5 called = 5
Result=7
f1 called = 1
f2 called = 2
f3 called = 3
f4 called = 4
f5 called = 5
inline=7
Multiple side effects are undefined
R1=16, i=5
R2=16, j=3

Optimisation level O1

Precedence is not the same as sub-exp<b></b>ression evaluation order
f1 called = 1
f2 called = 2
f3 called = 3
f4 called = 4
f5 called = 5
Result=7
f1 called = 1
f2 called = 2
f3 called = 3
f4 called = 4
f5 called = 5
inline=7
Multiple side effects are undefined
R1=16, i=5
R2=16, j=3

Optimisation level O2

Precedence is not the same as sub-exp<b></b>ression evaluation order
f1 called = 1
f2 called = 2
f3 called = 3
f4 called = 4
f5 called = 5
Result=7
f1 called = 1
f2 called = 2
f3 called = 3
f4 called = 4
f5 called = 5
inline=7
Multiple side effects are undefined
R1=16, i=5
R2=16, j=3

A good level of consistency, but now the order is essentially L->R as the code is read.

gcc (GCC) 4.2.4 (Ubuntu 4.2.4-1ubuntu4)
No Optimisation

Precedence is not the same as sub-exp<b></b>ression evaluation order
f1 called = 1
f2 called = 2
f3 called = 3
f4 called = 4
f5 called = 5
Result=7
f1 called = 1
f2 called = 2
f3 called = 3
f4 called = 4
f5 called = 5
inline=7
Multiple side effects are undefined
R1=16, i=5
R2=16, j=5

Optimisation level O2

Precedence is not the same as sub-exp<b></b>ression evaluation order
f1 called = 1
f2 called = 2
f3 called = 3
f4 called = 4
f5 called = 5
Result=7
f1 called = 1
f2 called = 2
f3 called = 3
f4 called = 4
f5 called = 5
inline=7
Multiple side effects are undefined
R1=16, i=5
R2=16, j=5

Like DMC, GCC evaluates left to right (in this test).
But the side-effect ridden evaluation of j now results in 5 and not 3.

lcc-win32 version 3.8. Compilation date: Mar 24 2008 11:52:21
No Optimisation

Precedence is not the same as sub-exp<b></b>ression evaluation order
f1 called = 1
f2 called = 2
f3 called = 3
f4 called = 4
f5 called = 5
Result=7
f1 called = 1
f2 called = 2
f3 called = 3
f4 called = 4
f5 called = 5
inline=7
Multiple side effects are undefined
R1=16, i=5
R2=16, j=3

Optimisation enabled

Precedence is not the same as sub-exp<b></b>ression evaluation order
f1 called = 1
f2 called = 2
f3 called = 3
f4 called = 4
f5 called = 5
Result=7
f1 called = 1
f2 called = 2
f3 called = 3
f4 called = 4
f5 called = 5
inline=7
Multiple side effects are undefined
R1=16, i=5
R2=16, j=3

No great surprise here.

VC6 – Microsoft ® 32-bit C/C++ Optimizing Compiler Version 12.00.8804
No Optimisation

Precedence is not the same as sub-exp<b></b>ression evaluation order
f1 called = 1
f2 called = 2
f3 called = 3
f4 called = 4
f5 called = 5
Result=7
f1 called = 1
f2 called = 2
f3 called = 3
f4 called = 4
f5 called = 5
inline=7
Multiple side effects are undefined
R1=16, i=5
R2=16, j=3

Optimisation level O1

Precedence is not the same as sub-exp<b></b>ression evaluation order
f5 called = 5
f4 called = 4
f3 called = 3
f2 called = 2
f1 called = 1
Result=7
f5 called = 5
f4 called = 4
f3 called = 3
f2 called = 2
f1 called = 1
inline=7
Multiple side effects are undefined
R1=16, i=5
R2=16, j=5

Optimisation level O2

Precedence is not the same as sub-exp<b></b>ression evaluation order
f5 called = 5
f4 called = 4
f3 called = 3
f2 called = 2
f1 called = 1
Result=7
f5 called = 5
f4 called = 4
f3 called = 3
f2 called = 2
f1 called = 1
inline=7
Multiple side effects are undefined
R1=16, i=5
R2=16, j=5

Totally crazy!
Turning on the optimiser calls the functions in the REVERSE order.
And the grossly undefined evaluation of j in test2 returns a different answer to the unoptimised code.
Is the compiler broke? Nope, the code is just rubbish.

VS2008 – Microsoft ® 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08
No Optimisation

Precedence is not the same as sub-exp<b></b>ression evaluation order
f1 called = 1
f2 called = 2
f3 called = 3
f4 called = 4
f5 called = 5
Result=7
f1 called = 1
f2 called = 2
f3 called = 3
f4 called = 4
f5 called = 5
inline=7
Multiple side effects are undefined
R1=16, i=5
R2=16, j=4

Optimisation level O1

Precedence is not the same as sub-exp<b></b>ression evaluation order
f4 called = 4
f5 called = 5
f2 called = 2
f3 called = 3
f1 called = 1
Result=7
f4 called = 4
f5 called = 5
f2 called = 2
f3 called = 3
f1 called = 1
inline=7
Multiple side effects are undefined
R1=16, i=5
R2=16, j=4

Optimisation level O2

Precedence is not the same as sub-exp<b></b>ression evaluation order
f1 called = 1
f2 called = 2
f3 called = 3
f4 called = 4
f5 called = 5
Result=7
f1 called = 1
f2 called = 2
f3 called = 3
f4 called = 4
f5 called = 5
inline=7
Multiple side effects are undefined
R1=16, i=5
R2=16, j=4

Now we’re cooking!
Imagine if you had code like this, and you upgraded your compiler from VC6 to VS2008.
Not only do you get a different order of function calls when turning on optimisation, the order is no longer the same between optimisation levels!.
And let’s give a big hand to the appearance of j=4 for the first time in our results.

Open Watcom C/C++ CL Clone for 386 Version 1.7
No Optimisation

Precedence is not the same as sub-exp<b></b>ression evaluation order
f2 called = 2
f3 called = 3
f1 called = 1
f4 called = 4
f5 called = 5
Result=7
f2 called = 2
f3 called = 3
f1 called = 1
f4 called = 4
f5 called = 5
inline=7
Multiple side effects are undefined
R1=20, i=5
R2=20, j=3

Optimisation level O1

Precedence is not the same as sub-exp<b></b>ression evaluation order
f2 called = 2
f3 called = 3
f1 called = 1
f4 called = 4
f5 called = 5
Result=7
f2 called = 2
f3 called = 3
f1 called = 1
f4 called = 4
f5 called = 5
inline=7
Multiple side effects are undefined
R1=20, i=5
R2=20, j=3

Optimisation level O2

Precedence is not the same as sub-exp<b></b>ression evaluation order
f2 called = 2
f3 called = 3
f1 called = 1
f4 called = 4
f5 called = 5
Result=7
f2 called = 2
f3 called = 3
f1 called = 1
f4 called = 4
f5 called = 5
inline=7
Multiple side effects are undefined
R1=20, i=5
R2=20, j=3

More variation – where will it stop?
The functions are back to being called in what seems to be precedence order.
But wait, R1=R2=20
Everything else up to now has been R1=R2=16

A related link is here.

Bravo to Salem! And all the other guys that contributed to this.🙂

Have questions about this code? Comments? Did you find a bug? Let me know!😀
Page created by G. (George) Samaras (DIT)

2 thoughts on “incDecUndefined.c

  1. Pingback: increment operator

  2. Pingback: Increment Operator Results

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s