- 操作员的行为

时间:2014-05-11 04:11:15

标签: c++ operators

--x x-1之间有什么区别? 我有一个计算前n个数之和的方法 我尝试使用100,结果如下:

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

当我添加--_suma时,结果为4950,当我添加_suma -1时结果为5050

任何人都可以解释原因吗? 请。

3 个答案:

答案 0 :(得分:6)

这是详细说明评估问题的顺序。

以下是C ++ 11标准关于评估顺序的内容:

  • 每个值计算和与全表达式相关的副作用在每个值计算和与要评估的下一个全表达式相关的副作用之前进行排序。 (§1.9[intro.execution] / p15)
  • 在运算符的结果的值计算之前,对运算符的操作数的值计算进行排序。 (§1.9[intro.execution] / p15)
  • 评估个体操作员的操作数和个体的子表达式 表达式没有排序。 (§1.9[intro.execution] / p15)
  • 当调用函数时(无论函数是否为内联函数),在执行每个表达式或语句之前,对与任何参数表达式或指定被调用函数的后缀表达式相关联的每个值计算和副作用进行排序。被调用函数的主体。 (§1.9[intro.execution] / p16)
  • 在执行被调用函数体之前或之后,在调用函数(包括其他函数调用)中的每个评估都没有特别顺序,关于被调用函数的执行是不确定的。 (§1.9[intro.execution] / p16)

如果对标量对象的副作用相对于同一标量对象的另一个副作用或使用相同标量对象的值进行的值计算未被排序,则行为未定义。 (§1.9[intro.execution] / p15)

现在我们可以将这些规则应用于此表达式:_suma + sumaRec(--_suma)

  1. +运算符的两个操作数的评估未被排序。编译器可以先评估_suma,然后sumaRec(--_suma),或者反过来。
  2. 在调用--_suma之前,sumaRec的值计算和副作用已按顺序排列。
  3. 关于sumaRec召唤本身,所有内容都是不确定的。也就是说,编译器可以在执行_suma函数中的语句之前或之后评估sumaRec,但不能在它期间评估{.1}。
  4. 在计算+运算符的结果之前,对+的两个操作数的值计算(但不是副作用)进行了排序。
  5. 特别是,因为对于使用相同标量对象的值的值计算,对标量对象(_suma)的副作用(存储递减的值)是未序的(计算值的计算) <{1}}的第一个操作数,行为未定义。

    符合标准的编译器可以执行以下任何操作:

    1. 首先评估+_suma秒,--_suma第三
    2. 首先评估sumaRec--_suma秒,sumaRec第三
    3. 首先评估_suma,然后评估--_suma秒,_suma第三
    4. 首先执行sumaRec的值计算,--_suma秒的值计算,_suma的副作用(存储递减的值)第三,--_suma第四
    5. 召唤出黑魔鬼,哄骗你的硬盘或其他任何想做的事情。如果行为未定义,则所有投注均已关闭。
    6. 值得强调的是,运算符优先级和评估顺序完全不同。运算符优先级意味着编译器将sumaRec这样的表达式解释为f() + g() * h()而不是f() + (g() * h()),但无法保证(f() + g()) * h()f(),并且g()将按任何特定顺序进行评估。实际上,如果此表达式在同一代码中出现两次,则编译器甚至不需要一致:评估顺序可以是一个h(),另一个是f(), g(), h()

      编辑:要注意GCC,如预期的那样emits a warning代码:

      g(), f(), h()

      在启用完整警告的情况下进行编译总是一个好主意。

答案 1 :(得分:3)

基本区别在于,当您执行x-1时,x的值保持不变。但是当你执行--x时,x的值会递减。所以,

让,

x=4;
y=x-1;

现在,在这种情况下,x是4,y是3.现在,对于相同的x = 4,

y = --x;

现在x和y都是3。

答案 2 :(得分:1)

前缀减量修改您正在使用的变量,不仅要将其发送到函数,还要在序列计算中。这就是你最终计算错误的原因。

我建议你把减法放在一个临时变量中,然后将该变量传递给你的函数。

相关问题