Sign in to follow this  
GDKnight

Programming Puzzel For You All

Recommended Posts

Evaluate the following in your head:
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;

int main()
{
	int i = 1;
	int k = (++i)+(++i)+(++i); 
	cout << k << endl;
	return 0;
}






Then evaluate the same thing in any compiler of your choice and check the output. Post what you thought and what you got, along with compiler used. [grin] Feel free to try other languages as well, this is quite intresting.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
One would hope that would generate an error or at least a warning if it's not valid C/C++...

Share this post


Link to post
Share on other sites
Quote:
Original post by MauMan
I thought I was going to get 9 and I got 12 with VS 2003 and 10 with g++ (GCC) 3.3.5 (Debian 1:3.3.5-13)


That is because it is undefined behaviour.

you could do this,

i=1;
i+=i++++i++i+i++i++;

And the result would be different from compiler to compiler.

Share this post


Link to post
Share on other sites
I think the reason gcc gives 10 is something like this: it parses the (++i)+(++i)+(++i) expression into a tree and then executes the left side, followed by the right side, of each node to give the final result.

Hence the order of execution looks like:
++i;
++i; /* Left/right of first + */
tmp = i + i;
++i;
tmp += i;

I think it would be straightforward to modify gcc to give "correct" (as in giving 9) behaviour, but it isn't required by the standard and this way optimises marginally better.

Share this post


Link to post
Share on other sites
Quote:
Original post by grekster
Anyway..... wouldnt it be better for the compiler to give an error when someone tries to do something like this?


I guess back in 1989 that kind of dependency tracking was too complicated to require in the standard. IMHO Java-like behaviour should be required because I can't really see it actually slowing anything down.

Share this post


Link to post
Share on other sites
I wonder why GCC uses a temporary in this case.

VS gives 12 with something like the following
(in psuedo asm)

inc a;
inc a;
inc a;
add a a;
add a a;

I guess VS must do instruction selection differently then GCC.

In any case, it's stupid to write (++i) + (++i) + (++i). So the standard is perfectly fine with undefined behaviour.

Share this post


Link to post
Share on other sites
I was just using the temporary variable for illustrative purposes. My point was that's how the code is initially converted into gccs internal representation which is why it gives 10 (since it's using what looks to me like the simplest parsing system). The MS compiler would seem to be evaluating all side effects first so it gives 12.

Share this post


Link to post
Share on other sites
it's easy. By standard this code:
int v = 0; std::cout << v+++v++;
results in undefined behaviour. Cause you cannot access on the same statement two time over a post-incremented variable.
My signature on italian forum was (for years)

do you think that C++ is an easy language?
int v = 0; std::cout << v+++v++;

it was a question that one person ask me when I begin my first programming-related work.

Share this post


Link to post
Share on other sites
Another one :) What shall this one print, was brought up by friend of mine some time ago:

void AddVertex( float x, float y, float z )
{
printf( "x:%f, y:%f, z:%f\n", x, y, z );
}

int _tmain(int argc, _TCHAR* argv[])
{
float verts[] =
{
1, 2, 3,
4, 5, 6,
7, 8, 9,
10, 11, 12,
};
const size_t nVerts = 4;
float* ptr = &verts[0];
for( size_t i = 0; i < nVerts; i++ )
AddVertex( *ptr++, *ptr++, *ptr++ );
getchar();
return 0;
}



the code thing fails to show the *ptr<plus><plus> correctly...

Share this post


Link to post
Share on other sites
I actually got bitten by this, believe it or not. Didn't take me long to realise what had gone wrong though.

You see, I was writing a (stupid, testing) virtual machine. I had some bytecode that was just a big array of ints. So, I wen't like this:

for(int i = 0; i < arraySize; ++i)
{
switch(byteCode[i])
{
case Foo:
Foo(byteCode[++i], byteCode[++i]); //Ouch, wrong parameters.
break;
}
}

Share this post


Link to post
Share on other sites
Quote:
Original post by memon
the code thing fails to show the *ptr<plus><plus> correctly...

It's not supposed to do what you think. One of the sequence points in C++ is:

after evaluation of all a function's parameters but before the first expression within the function is executed

So you dereference the first float in verts[] 3 times and pass those identical values to AddVertex. Before the printf statement ptr gets incremented 3 times and points to the 4th element.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this