【问题标题】:When should a function return what?函数什么时候应该返回什么?
【发布时间】:2019-07-08 16:48:21
【问题描述】:

我对函数的返回类型有点困惑,特别是什么时候返回什么。如果我们有任意函数,比如说 min(x,y),它应该根据 if 语句返回,我应该在它们的范围之外返回什么,这是函数声明所要求的。我了解到使用“return 0”或“return 1”很常见,但我不明白为什么会这样,以及为什么它不能只返回 if 的任何一个 return 语句。

// compute difference largest - smallest
int   diff(x, y)
{
   if (x > y)
    return x - y;
   if (y > x)
    return y - x;
   if (x == y)
    return 0;
   return 1;
}

【问题讨论】:

  • 一个函数应该返回你想要返回给调用者的值。该值是多少取决于函数的用途。通常用0和1来表示成功和失败,或者失败和成功,或者假和真。通常,函数返回一个根据其参数计算的值。对于min 函数,min 可能代表“最小值”,它应该返回其两个参数的最小值。在相等的情况下,min 函数通常不会返回 1(除非两个数字恰好为 1)。
  • 不应调用返回两个值的绝对差的函数min。它可以称为AbsoluteDifferenceabsdiff 或类似的名称。在最简单的形式中,如果两个数字相等,这样的函数将返回零。如果你想返回一个相等的数字,你可以称之为ClampedAbsoluteDifference
  • 请注意,在现代 C 中,int min(x, y) 不是正确的声明。您需要参数的类型,例如int min(int x, int y)
  • @EricPostpischil 但为什么我必须声明两次;如果我希望它返回差异。为什么函数不跳过 return 1,只返回 if 中的任何一个,如果它是真的,然后终止?
  • @Mike 两次声明什么? return 1; 永远不会被执行,因为所有三种可能的情况都已经处理过了。因此您可以删除return 1;。或者最好按照 EricPostpischil 的回答建议编写函数。

标签: c return return-value return-type


【解决方案1】:
  • 如果X 大于Y,则返回X-Y (很明显)
  • 如果Y 大于X,则返回Y-X (也很明显)
  • 如果XY 相等,您认为应该返回什么?
    如果它们相等,X-YY-X0,所以这并不重要,不是吗?

你的最后一个子句可以写成:

return x-y;
return y-x;
return 0; 

因为它们两个值相等,所以它们都将评估为0

重要的部分是确保函数的契约得到维护。
根据 cmets,该函数声称它将返回两个值之间的差值。所以它应该返回差异在所有情况下,无论较大的值是 X、Y 还是它们相等。

您的函数名称极具误导性。因为它被命名为min,这意味着它将返回 minimum 值,而不是差值。为了清楚起见,您应该将函数名称更改为 diffdelta


最终,编写函数的更简单方法是:

// compute largest - smallest
int diff(int x, int y)
{
   if (x > y)
    return x - y;   // Handles X is bigger than Y
   else
    return y - x;   // Handles Y bigger than X, *or* X and Y are the same.
}

最后,我会考虑一些非常短的版本。

int diff(int x, int y) { return x>y? x-y:y-x; }
int diff(int x, int y) { return abs(x-y);     }

【讨论】:

  • 是的,但是如果我用 printf 运行它,它会返回 1。这是为什么呢?
  • @Mike 当你用两个相等的值运行它时,它返回1,因为你告诉它返回1
【解决方案2】:

编译器需要确保你返回一些东西。如果你在 if 语句中有返回值,比如你有,编译器如何判断你是否覆盖了所有情况?

即使您执行以下代码,编译器如何知道您在所有情况下都会返回?因此,此代码将引发错误:

int min(int x, int y)
{
    if (x > y)
        return x - y;
    if (y > x)
        return y - x;
    if (x==y)
        return 1;
}

你怎么能解决这个问题?你可以在函数的末尾写另一个返回,就像你一样。现在编译器知道无论发生什么你都会返回一个值。

但是,有更好的方法可以确保您始终返回一个值。例如,您可以使用 else 语句作为包罗万象:

int min(int x, int y)
{
    if (x > y)
        return x - y;
    if (y > x)
        return y - x;
    else
        return 1;
}

因为 else 保证捕获所有情况,编译器对此很满意,并且不会抛出任何错误。

【讨论】:

  • 第一版min函数不会报错,int min(x, y)反正是错的。在 C 中也不例外。
  • @Jabberwocky:int min(x, y) 有什么问题?它不是原型,当然,它不应该由当前千年中的任何人编写,它可能应该是 int min(x, y) int x, y; { …function body… },但我在您的评论中没有看到细微差别。
  • @Jabberwocky 我在 gcc 上抛出一个错误(控制到达非 void 函数的末尾)。至于减速,我从问题中复制并忘记修复。现在会这样做。
  • @hat 很奇怪,我没有收到错误:检查这里:godbolt.org/z/On5feX
  • 即使函数的返回类型不是 void,只要调用者不尝试使用返回值,C 标准也不要求它返回值。 (这对于获取值或设置值的函数很有用,具体取决于给定的参数。“设置值”路径不需要返回值。)因此编译器可以警告如果存在没有return 的控制路径,但是,当它处于标准兼容模式时,它必须成功转换这样的功能。
【解决方案3】:

对于计算两个值之间的差值的函数,如果这两个值之间的差值为 1,则仅返回 1,如果它们相等,则返回 0。

有一门编程学派说,最好在函数末尾有一个返回,而不是分散在各处的多个返回。不是在每个分支中返回差异,而是计算并存储该差异,并在函数末尾返回它:

int diff( int x, int y );
{
  int delta = 0;

  if ( x >= y )
    delta = x - y;
  else 
    delta = y - x;

  return delta;
}

像大多数编程规则一样,也有例外。如果不满足某个条件,有时您想要立即退出。知道什么时候哪种方法更好是一个经验问题。

【讨论】:

    【解决方案4】:

    函数的返回类型在定义中指定,int 在您的情况下。 实际上,您需要指定输入参数的类型(x, y),然后输出的类型通常是从​​它们的类型派生的——比如函数中的 2/3 情况,最后一个是整数(0)。

    备注: 您还需要为函数选择更好的名称。

    【讨论】:

    • int min(x, y) { …function body… } 是非原型(K&R 或准标准)C 定义。该标准的当前版本仍然允许它,尽管该符号被标记为过时(尽管 C99 及更高版本可能需要int min(x, y) int x, y; { …function body… })。
    猜你喜欢
    • 2020-07-16
    • 1970-01-01
    • 2017-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-21
    • 1970-01-01
    相关资源
    最近更新 更多