简体   繁体   English

—运算符的行为

[英]Behavior of — operator

What's the difference between --x of x-1 ? --x of x-1x-1之间有什么区别? I have a method which calculates the sum of the first n numbers I try with 100 and the result is the following: 我有一种方法来计算我尝试使用100的前n个数字的总和,结果如下:

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 当我放--_suma ,结果是4950 ;当我放_suma -1 ,结果是5050

Can anyone explain why? 谁能解释为什么? Please. 请。

This is to elaborate on the order of evaluation issue. 这是为了详细说明评估问题的顺序。

Here's what the C++11 standard says about order of evaluation: 以下是C ++ 11标准关于评估顺序的说明:

  • 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) (第1.9节[介绍执行] / 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) (第1.9节[介绍执行] / p15)
  • Evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. 没有对单个运算符的操作数和单个表达式的子表达式求值的顺序。 (§1.9 [intro.execution]/p15) (第1.9节[介绍执行] / 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) (第1.9节[介绍执行] / 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) (第1.9节[介绍执行] / 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) (第1.9节[介绍执行] / p15)

Now we can apply these rules to this expression: _suma + sumaRec(--_suma) . 现在我们可以将这些规则应用于此表达式: _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. 编译器可以自由地先评估_suma ,然后评估_suma sumaRec(--_suma)或相反。
  2. The value computation and side effects of --_suma is sequenced before the call to sumaRec . --_suma的值计算和副作用在调用sumaRec之前进行sumaRec
  3. Everything is indeterminately sequenced with respect to the sumaRec call itself; 相对于sumaRec调用本身,所有内容都不确定地排序。 ie, the compiler could evaluate _suma either before or after the execution of the statements in the sumaRec function, but not during it. 也就是说,编译器可以在sumaRec函数中的语句执行之前或之后评估_suma ,但不能在此期间sumaRec
  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. 特别是,由于对于使用同一个标量对象的值( +的第一个操作数的值的计算)进行的值计算,对标量对象( _suma )的副作用(存储递减的值)没有_suma行为是不确定的。

A conforming compiler can do any of the following: 合格的编译器可以执行以下任一操作:

  1. evaluate _suma first, --_suma second, sumaRec third 先评估_suma--_suma评估_suma --_sumasumaRec评估_suma
  2. evaluate --_suma first, sumaRec second, _suma third 评估--_suma首先, sumaRec第二, _suma第三
  3. evaluate --_suma first, _suma second, and sumaRec third 评价--_suma第一, _suma第二和sumaRec第三
  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 首先执行--_suma的值计算,第二次执行--_suma的值计算, _suma次执行--_suma--_suma (存储递减值),第四次执行sumaRec
  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. 运算符优先级意味着编译器将像f() + g() * h()的表达式解释为f() + (g() * h())而不是(f() + g()) * h() ,但是不能保证以任何特定顺序对f()g()h()进行求值。 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. 实际上,如果此表达式在同一代码中出现两次,则甚至不需要编译器保持一致 :求值顺序可以是f(), g(), h()g(), f(), h()在另一个。

Edit: To note that GCC, as expected, emits a warning for this code: 编辑:要注意,按预期,GCC 为此代码发出警告

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. 基本区别在于,当您执行x-1 ,x的值保持不变。 But when you do --x , the value of x is decremented. 但是,当您执行--x ,x的值将递减。 So, 所以,

Let, 让,

x=4;
y=x-1;

Now, in this case, x is 4 and y is 3. Now, for same x=4, 现在,在这种情况下,x为4,y为3。对于相同的x = 4,

y = --x;

now x and y both are 3. 现在x和y均为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. 我建议您将减法放在temp变量中,然后将该变量传递给函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM