此代码给出的输出为 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。为什么会这样呢?
在第二个程序的这一行:
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)