Compiler related?
here're sample codes:
int fun(int n)
{
if(++n==5)
return n++;
return n*fun(n++);
}
void main()
{
int i=1;
int sum=fun(i);
cout<<sum<<endl;
}
(first, I knew the codes above applied bad coding style. here pls ignore it, i wanna know some other behaviors of C++/compiler)
I used VS2005 to compile and execute it, i got a sum =300 as the reslult, while on TC and gcc the result wassum = 120. i looked into the assembly and found the difference happened because of different implementation of the statementn*fun(n++).
my question is -Did i get the expected result? Is the result/behavior truely compiler dependent?
and subsequently, i got300 and120 in VS2005, when i changed the build mode betweenDebug andRelease .(Debug-300, Release-120).
sowhat are the differences, which can cause the result above, of sepcified settings for runtime between DEBUG and RELEASE? really want to know what's happened...
i'm new in C++, thanks for your help in advance!
-rick
[2416 byte] By [
Rick.H] at [2007-12-24]
n * fun(n++) is undefined behavior. Compiler can do either
n * fun(n++) // actually n * fun(n)
or
fun(n++) * n // actually fun(n) * (n + 1)
because the order of evaluation of expressions is undefined in C/C++. Because n++ is used in a function call the side effect of the ++ operator takes effect before multiplying with n so you actually multiply with (n + 1).
The difference appears between debug and release because release mode optimizes code and it likely that it generates code that changes the order of evaluation.
>>>>my question is - Did i get the expected result? Is the result/behavior truly compiler dependent?
how we can say that?
>>> return n++;
this is same as "return n" since it is post increment. i.e increment will happen only after returning from function :)
return n*fun(n++);
The reason for the undefined behavior in the above code is because of the optimization you have given to the build. In the debug build, normally the optimization will be disabled. So it will work as described in the operator precedence. i.e incrementation will happen because it is part of function call and then * operator will execute. but in the release build the optimization will happen. I don't know more about what's going inside on operator precedence while optimizing the code.
If you give "Maximize your speed" (/O2) you will get the same result of release build ( assume that in the release build, it's configured for Maximize speed)
If possible try to break down the code to an understandable manner.
Usually, the optimization is the deciding factor in such situations. That's not the case here, though. The "culprit", if you can call it that; seeing as the evaluation order isn't specified by the standard, is whether or not the basic runtime checks are enabled. In release build, these are switched off per default, while in debug they are set to both stack frames and unitialized variables. The code generated to do these checks, happens to break the code apart in a different manner than what is done with no checking, hence the different results.