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

Who do these two C programs with a recursive function and static variable have different outputs?

此代码输出为 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));
}

在第一个代码中,我在 return 语句之前增加了 num,在第二个代码中,我在 return 语句中预先增加了 num。 第一个代码似乎评估为 5*5*5,而第二个代码评估为 3*4*5。为什么会这样?

在第二个程序的这一行:

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

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

这个表达式的各个操作数的计算是未排序的,这意味着要么先计算num,要么调用func首先.

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

所以这里没有未定义的行为,但是由于子表达式的未排序计算,结果是 未指定

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

return num*func(--a);

和以前一样,如果先计算 num,那么就会看到当前值。如果首先评估函数调用,则将读取 num 的更新值。

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

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