查找 GCD:并非所有控制路径都返回值

finding gcd: not all control paths return a value

本文关键字:控制 路径 返回值 GCD 查找      更新时间:2023-10-16
int gcd(int a, int b) {
if (b == 0)
return a;
else {
gcd(b, a % b);
}
}

当我试图计算最大公约数时, 我知道我必须打电话给return gcd(b,a%b)而不是gcd(b,a%b). 但我不明白原因。 b在某个时候不会变成0吗?

第一次调用函数时。 如果b!=0它将继续执行else gcd(b, a % b);但是您第一次调用的函数没有返回值。

以下代码将帮助您了解递归:

int gcd(int a, int b) {
if (b == 0)
return a;
else {
return gcd(b, a % b);
}
}
int calc_gcd(int a, int b) {
if (b == 0)
return a;
else {
gcd(b, a % b);
// return ?
}
}

调用函数calc_gcd等效于在代码中调用gcd。 缺少返回值。 正确的递归函数的工作方式如下:

gcd0                                         ... return value to user
gcd1                                 .... ↑ 
gcd2                         .... ↑
gcd3 .... pass value to ↑

你真的不必做

return gcd(b,a%b)

但这是最简单的方法。

您似乎明白,在所有情况下都必须从具有类似头部的函数中返回一个 int

int gcd(int a, int b) 

在 if 的两个分支中执行操作是一种简短的方法。

可以说,对于可读性、可维护性、健壮性等次要目标,int-return 函数的最后一个语句应该始终是return SomeInt;。但是,要做到这一点并不容易,因为许多静态分析工具也不会抱怨"无法访问代码"。一个局部变量int returnValue,初始化为明智选择的默认值并写入所有分支中,可以让你到达那里。
但同样,一些工具会抱怨将值写入变量,然后在使用之前总是被覆盖......因此,默认的初始化可能是a,然后不会在"then"中被覆盖。让分析工具快乐有时是一种循环游戏......

顺便说一下,你显示的代码可能(绝对不能保证(确实有效,因为编译器有时会默认返回最后一个计算结果,即使它被忽略了。但你绝对不应该依赖它,并且应该得到任何你得到的抱怨,无论是人类还是工具。我们可以放心地认为这是一个坏主意(tm(。