Question

What's the difference between --x of x-1? I have a method which calculates the sum of the first n numbers I try with 100 and the result is the following:

int sumaRec(int _suma){
    if (_suma > 0)
    {
        return _suma + sumaRec(--_suma);
    }
    else
        return 0;
}

When i put --_suma the result is 4950 and when i put _suma -1 the result is 5050

Can anyone explain why? Please.

Was it helpful?

Solution 3

The prefix decrement is modifying the variable you are using not only to send it to the function but also in your sequence calculation. That's why you end up with a wrong calculation.

I suggest you put the subtraction in a temp variable and just pass that variable to your function.

OTHER TIPS

This is to elaborate on the order of evaluation issue.

Here's what the C++11 standard says about order of evaluation:

  • Every value computation and side effect associated with a full-expression is sequenced before every value computation and side effect associated with the next full-expression to be evaluated. (§1.9 [intro.execution]/p15)
  • The value computations of the operands of an operator are sequenced before the value computation of the result of the operator. (§1.9 [intro.execution]/p15)
  • Evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. (§1.9 [intro.execution]/p15)
  • When calling a function (whether or not the function is inline), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function. (§1.9 [intro.execution]/p16)
  • 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. (§1.9 [intro.execution]/p16)

If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. (§1.9 [intro.execution]/p15)

Now we can apply these rules to this expression: _suma + sumaRec(--_suma).

  1. The evaluations of the two operands of the + operator is unsequenced. The compiler is free to evaluate _suma first, then sumaRec(--_suma), or the reverse.
  2. The value computation and side effects of --_suma is sequenced before the call to sumaRec.
  3. Everything is indeterminately sequenced with respect to the sumaRec call itself; i.e., the compiler could evaluate _suma either before or after the execution of the statements in the sumaRec function, but not during it.
  4. The value computations, but not the side effect, of the two operands of + are sequenced before computation of the result of the + operator.

In particular, because the side effect (storing the decremented value) on a scalar object (_suma) is unsequenced with respect to a value computation using the value of the same scalar object (computation of the value of the first operand of +), the behavior is undefined.

A conforming compiler can do any of the following:

  1. evaluate _suma first, --_suma second, sumaRec third
  2. evaluate --_suma first, sumaRec second, _suma third
  3. evaluate --_suma first, _suma second, and sumaRec third
  4. perform the value computation of --_suma first, the value computation of _suma second, the side effect of --_suma (storing the decremented value) third, and sumaRec fourth
  5. conjure nasal demons, chomp up your hard drive, or anything else it wants to do. When the behavior is undefined, all bets are off.

It is worth emphasizing that operator precedence and order of evaluation are entirely different things. Operator precedence means that an expression like f() + g() * h() is interpreted by the compiler as f() + (g() * h()) and not (f() + g()) * h(), but there is no guarantee whatsoever that f(), g(), and h() will be evaluated in any particular order. In fact, if this expression appears twice in the same code, the compiler is not even required to be consistent: the evaluation order can be f(), g(), h() in one and g(), f(), h() in another.

Edit: To note that GCC, as expected, emits a warning for this code:

g++ -march=native -std=c++11 -Wall -Wextra -pedantic main.cpp && ./a.out
main.cpp: In function 'int sumaRec(int)':
main.cpp:9:39: warning: operation on '_suma' may be undefined [-Wsequence-point]
         return _suma + sumaRec(--_suma);
                                       ^

It's always a good idea to compile with full warnings enabled.

the basic difference is that, when you do x-1, the value of x remains the same. But when you do --x, the value of x is decremented. So,

Let,

x=4;
y=x-1;

Now, in this case, x is 4 and y is 3. Now, for same x=4,

y = --x;

now x and y both are 3.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top