C++ C+中的减量运算符+;

C++ C+中的减量运算符+;,c++,function,recursion,operator-keyword,C++,Function,Recursion,Operator Keyword,我来自C语言背景,现在我正在学习使用C语言的OOP++ 下面是一个计算阶乘的程序 #include <iostream> using namespace std; void main () { char dummy; _int16 numb; cout << "Enter a number: "; cin >> numb; double facto(_int16); cout << "fact

我来自C语言背景,现在我正在学习使用C语言的OOP++

下面是一个计算阶乘的程序

#include <iostream>

using namespace std;

void main ()
{
    char dummy;
    _int16 numb;
    cout << "Enter a number: ";
    cin >> numb;

    double facto(_int16);

    cout << "factorial = " <<facto(numb);
    cin >> dummy;
}

double facto( _int16 n )
{
    if ( n>1 )
        return ( n*facto(n-1) );
    else
        return 1;
}
用这个

    return ( n*facto(n--) );
那就不行了。n--不会将n减少1。为什么?

我正在使用Visual Studio 2012

编辑:明白了!谢谢:)

*此外,我还想补充以下答案:使用--n将导致
n
在语句执行之前递减。因此,由于预减量,表达式将变成
(n-1)*事实(n-1)
。这就是为什么在这种情况下最好不要使用预减量*

当前,通过使用
n--
n
的原始值和未修改的值传递到
中,从而导致循环

您需要改用
n-1
。从表面上看,使用
--n
很有诱惑力,因为这将减少
n
并计算为新的(较低的)值。但是,
--n
将给您未定义的行为,因为您将函数返回值预乘以
n
,并且由于
*
不是序列点,
n
的值定义不明确

(顺便说一句,C中的行为应该是相同的)

[编辑:在未定义的行为点上确认Mike Seymour]。

返回(n*事实(n-)

您正在使用后减量运算符。
发生的情况是,将
n
的值传递给函数,然后将其递减。这不会影响已经传递给函数的值

编辑::下面的解释只是为了让OP更好地理解Post和Pre减量的用法OP代码的正确答案是,
n*事实(n-1)
@OP:您不应该在代码的这一部分中进行任何预修改,因为它将调用未定义的行为,这是由于变量
n
的未顺序修改造成的

减量前后:: 如果要在传递值之前递减变量,必须使用pre decrement()。另一方面,后减量在变量减量之前对表达式求值:

int n = 10, x;
x = --n;                // both are 9

为什么不在您的案例中使用预减量?:
n*事实(n--)
原因。 为什么?

§5/4中的标准规定:

在上一个序列点和下一个序列点之间,应显示一个标量对象 通过对 表情

之前的值仅可用于确定待确定的值 储存的


这意味着,在两个序列点之间,对变量的修改不得超过一次,如果在完整表达式中写入对象,则在同一表达式中对该变量的任何和所有访问都必须直接参与待写入值的计算。

“n--不会将n减1”-不正确。下次验证你的假设。注意:它的工作原理与C中的一样。鉴于最近的安全警报,您可能希望开始在if块周围使用{}。另外,
使用名称空间std
形式不好。@AlexChamberlain什么安全警报?
n*fact(n--)
是未定义的行为。clang说,
警告:未排序的修改和对'n'的访问
@TomFenech:Google表示“goto fail”,例如最近的一个例子。添加第二行很容易,但忘记了添加大括号,结果是在不应该的时候无条件执行代码。(在本例中,它导致绕过一个重要的安全检查。)不,您不需要使用
--n
。这在这里给出了未定义的行为(因为有第二个未排序的访问
n
);在这之后,
n
的值是未使用的,所以无论如何修改它的值都没有意义。它应该是
n-1
@Paranaix Right,但是
n
*
的左操作数)是在函数调用之前还是之后求值的?我认为(可能是错误的),函数调用确保减量发生在(I)函数调用和(ii)之前
*
@Bathsheba:否左侧的
n
求值。例如,它可以不按顺序求值
n
--n
,然后调用函数,然后求值
*
的结果。确定。我将修改答案。请看关于“未定义行为”的其他答案@DieterLücking:这是从问题中复制代码,以描述错误原因,而不是建议使用此代码。(未定义的行为是错误的第二个原因,但不是特别相关。)
int n = 10, x;
x = --n;                // both are 9
int n = 10, x;
x = n--;                // x = 10, i = 9