我无法理解为什么我的代码输出是2,2,3
,而且当我删除u ++时,它的输出是2,5,5
我正在Windows 7上使用带有gcc的code_block
我尝试空运行我的代码,但其输出与我计算的结果不同
int f(int);
int u = 1;
int main()
{
int n = 3;
//scanf("%d", &n);
f(n);
}
int f(int n)
{
if (n == 0)
{
return 2;
}
else
printf(" %d \n", f(n - 1));
u++;
}
我期望2,1,0
可能是我错了,但我不明白为什么输出是2,2,3
,而当我删除u ++时,这会给我带来很大的困惑
答案 0 :(得分:1)
在n != 0
路径中,您的函数未明确返回值,并且返回的值是不确定的。
我也不清楚为什么n==0
时为什么返回2-您对此值不做任何操作,而且似乎是任意的。
考虑一下:
int f( int n )
{
if( n != 0 )
{
n-- ;
printf( " %d \n", n );
n = f( n ) ;
}
return n ;
}
这既简单(没有else
块),又具有明确定义的返回值的单出口。
答案 1 :(得分:-2)
通过以下方式进行跟踪:
f(3)
f(3)
调用printf("%d", f(2))
-必须在调用f(2)
之前评估printf
f(2)
调用printf("%d", f(1))
-必须在调用f(1)
之前评估printf
f(1)
调用printf("%d", f(0))
-必须在调用f(0)
之前评估printf
f(0)
返回2
printf
进行第4步的f(0)
调用,结果为2
-这是输出中的第一个2
u
递增,现在保留2
f(1)
退出而没有返回值-您在此处调用了未定义的行为,从现在开始任何都是可能的。可能发生的情况是u++
的结果已存储在用于从函数返回值的同一寄存器中。printf
的结果进行步骤3的f(1)
调用。 u++
递增,现在为3。f(2)
退出而不返回值。printf
的结果进行步骤2的f(2)
调用。同样,可能发生的情况是u++
的结果已存储在用于从函数返回值的同一寄存器中。这就是为什么在取出u++
语句时看到不同的结果的原因。
注意-我说这是基于过去观察到的真实行为的可能解释;但是,未定义行为的关键属性是未定义-它不必保持一致或可重复。每次运行的输出可能会有所不同,而无需重建代码。您看到该输出的原因可能完全不同。关键要解决的是,您的代码中有一个错误(必须在f
时不从n > 0
返回值)。
问题是,f()
会返回什么n > 0
??一旦弄清楚了,就为该值添加一个明确的回报。例如,如果f()
应该返回n
,则您需要类似
int f( int n )
{
if ( n == 0 )
{
return 2;
}
/**
* Don’t really need an "else" here
*/
printf( " %d\n", f( n - 1 ));
u++;
return n;
}
您还需要添加一个检查,以确保n
不小于0
,否则您的代码将递归直到您碰到INT_MIN
并下溢,然后猜测行为在带符号整数下溢(和溢出)上也未定义。
答案 2 :(得分:-3)
这是解决方案:
int f(int);
int main() {
int n;
scanf("%d", &n);
f(n);
}
int f(int n) {
if (n == 0) return 0;
else {
printf(" %d \n", n-1);
f(n - 1);
}
}
您应该避免使用全局变量,并且不需要变量u。