这两个有递归函数和静态变量的C程序为什么有不同的输出?



这段代码给出的输出为125

#include<stdio.h>
int func(int a)
{
static int num = 2;
if(a==0) return 1;
num++; 
return num*func(--a);
}
int main()
{
printf("%d", func(3));
}

而这段代码给出的输出为60

#include<stdio.h>
int func(int a)
{
static int num = 2;
if(a==0) return 1;
return (++num)*func(--a);
}
int main()
{
printf("%d", func(3));
}

在第一个代码中,我在返回语句之前增加了num,在第二个代码中,我在返回语句中预增加了num。第一个代码的计算结果似乎是5*5*5,而第二个代码的计算结果是3*4*5。为什么会这样呢?

在第二个程序的这一行:

return (++num)*func(--a);

num的值作为副作用增加,func的函数调用也修改了num

该表达式的单个操作数的求值为unsequenced,这意味着可以先求num,也可以先调用func

func的调用引入了一个序列点。因此,如果先计算++num,则在实际调用func之前应用增加num的副作用。另一方面,如果对func的调用首先求值,则num将在函数调用内部被修改,然后对num的读取和更新将看到更新后的值。然而,并不能保证其中一个会先发生。

所以这里没有未定义行为,但是结果是未指定的由于子表达式的求值没有顺序。

第一个程序也有类似的问题,即使num在同一语句中没有递增:

return num*func(--a);

和前面一样,如果先计算num,则显示当前值。如果先对函数调用求值,则将读取num的更新值。

要从程序中获得确定性行为,您需要将静态变量的当前值复制到非静态变量中,并使用该值乘以函数结果。

int func(int a)
{
static int num = 2;
if(a==0) return 1;
int num_tmp = ++num;
return num_tmp*func(--a);
}

最新更新