我来自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语句
return ( n*facto(n-1) );
用这个
return ( n*facto(n--) );
然后它不起作用。 n - 不会将 n 减少1.为什么?
我正在使用Visual Studio 2012
编辑:知道了!谢谢:))
* 另外,我想补充下面的答案:使用--n会导致n
在执行语句之前递减。因此,由于预先递减,表达式将变为(n-1)*facto(n-1)
。这就是为什么在这种情况下最好不要使用预减量*
答案 0 :(得分:12)
目前,通过使用n--
,您将n
的原始且未经修改的值传递给导致循环的facto
。
您需要使用n - 1
代替。从表面上看,它会诱人使用--n
因为那会减少n
并评估新的(较低)值。但--n
会为您提供未定义的行为,因为您将函数返回值预先乘以n
,因为*
不是序列点< / em>,n
的值没有明确定义。
(顺便说一下,C中的行为是相同的)。
[编辑:承认Mike Seymour关于未定义的行为点]。
答案 1 :(得分:6)
编辑:: 下面的解释只是为了让OP更好地了解它们,以便了解Post和Pre-Decrement的用法。 OP代码的正确答案是, n*facto(n - 1)
。 @OP:你不应该在代码的那一部分做任何预先减少,因为它会因为变量n
的无序修改而调用未定义的行为。
前后减少:: 如果要在传递值之前递减变量,则必须使用预递减(wiki-link)。另一方面,后递减在变量递减之前计算表达式:
int n = 10, x;
x = --n; // both are 9
和
int n = 10, x;
x = n--; // x = 10, i = 9
为什么不在你的情况下使用预先减少?:: n*facto(n--)
导致UB。
的为什么吗
§5/ 4中的标准说
在前一个和下一个序列点之间,标量对象应该 通过评估a,最多修改一次存储值 表达
和
只能访问先前值以确定值 存储
这意味着,在两个序列点之间,变量不能被多次修改,如果一个对象被写入一个完整的表达式,那么在同一个表达式中对它的任何和所有访问都必须直接参与计算要写的价值。
答案 2 :(得分:0)
return ( n*facto(n--) );
您正在使用post decrement运算符。
会发生什么,您将n
的值传递给函数,然后递减它。这不会影响已传递给函数的值