这段代码给出的输出为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);
}