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

pun*_*red 2 c static function

此代码给出的输出为 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));
}
Run Code Online (Sandbox Code Playgroud)

虽然此代码给出的输出为 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));
}
Run Code Online (Sandbox Code Playgroud)

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

dbu*_*ush 6

在第二个程序的这一行:

return (++num)*func(--a);
Run Code Online (Sandbox Code Playgroud)

num作为副作用,的值会增加,并且对 的函数调用func也会修改num

该表达式的各个操作数的求值是无序的,这意味着num可以先求值,也func可以先调用。

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

因此,这里不存在未定义的行为,但由于子表达式的求值未排序,结果未指定。

第一个程序也有类似的问题,尽管num在同一条语句中没有增加:

return num*func(--a);
Run Code Online (Sandbox Code Playgroud)

和以前一样,ifnum首先被评估,然后看到当前值。如果首先评估函数调用,则将num读取更新后的值。

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

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