为什么 C 让你忽略函数的返回值?

Why does C let you ignore returned values from functions?

假设我有以下 C 代码:

int return_one()
{
    return 1;
}

int main(void)
{
    return_one();
}

在主函数中,我调用函数 return_one() 并忽略 return 值。编译器对我忽略此值没有问题。

为什么这样可以?它是 C 创建者的任意设计选择吗?或者是否有不要求调用函数使用 return 值的实际原因?

因为很多 return 值人们都不关心,所以为什么要强迫他们使用它们?

的标准 C 函数 return 值基本上 从未 看过。想一想您曾经看过的所有 C 代码。你曾经见过有人用printf函数族的return值做任何事情吗?因为他们都有一个,但你永远不会知道看现实世界的代码。如果对 printf 的每次调用都必须在其前面加上一个明确的“我不关心 return 值”语法位(例如 (void)),因为 99.99有 % 的时间,您实际上并不关心打印了多少字节,但是 printf 计算并且 return 无论如何?基本上,您可以不使用 return 值,因为没有必要强迫您这样做,而且通常也不需要。

tl;dr:您可以编写代码,使 return 值始终相关 - 在这种情况下,忽略它们将是一个错误。但是,某些(特别是较旧的)代码不能那样工作,忽略 return 值可能是合理的。

What is the logic as to why this okay? Was it an arbitrary design choice from the C creators?

这不仅仅是 C 创建者的选择,许多其他语言也允许这样做 - 事实上,我想不出忽略 return 值被认为是错误的语言。

这样做的实际动机主要是函数的 return 值通常用于报告错误,或报告函数所做工作的详细信息。有时,您对这些细节不感兴趣,所以您会忽略它们。一个常见的例子是 C 函数 printf,它 return 是打印的字符数。虽然这有时可能有用,但通常没有用,因此 printf 的 return 值通常会被忽略。

这可以说是一个糟糕的设计(无论是在您的代码中,还是在 return 没人想要的功能中),但这是既定的做法,因此 C(与其他语言一样)支持这一点。

Or is there a practical reason for not requiring the calling function to use the return value?

不,没有实际理由忽略 return 值 - 除非您不想要它们。


虽然以上是历史惯例,但现在许多人认为忽略 return 值是一个问题(或更深层次问题的症状):

  • 如果return值是为了报错,忽略它通常可以,但如果真的有错误就会出现问题。这现在通常被认为是一个坏主意。
  • 通常,如果您可以忽略 return 值,则表示该函数正在导致 side-effects(否则调用它将毫无意义)。许多人认为最好让函数只做一件事——要么产生副作用(return 什么都不做),要么return 一个值(并且没有副作用)。后者通常称为 pure function(输出的附加条件仅取决于输入)。这种分离使得更容易理解软件——如果你使用它,忽略 return 值必然是一个错误,因为函数 return 返回结果什么都不做,所以如果你忽略结果,调用毫无意义。

所以换句话说:如果您遵循某些约定,就不会有您想忽略 return 值的情况,在这种情况下忽略它们通常是错误的。没有这些约定,可能有充分的理由忽略它们,因此没有通用规则。

我认为主要原因是通常的原因——历史。

在C标准之前,没有选项可以用void表示'no return value'。函数 returned 一个 int 除非你指定它们 returned 一些其他类型,但其他类型不能是 void(它不存在)。因此,return 值无关紧要的函数没有 return 值 — 即使该函数隐式 returning 类型 int。 (通常,return 类型被省略——函数隐式 returning 一个 int。)如果调用代码试图使用一个值但被调用函数没有return 一个值。

所有这些都意味着忽略函数的 return 值是司空见惯的事情——尤其是名义上 return 编辑了 int 但实际上没有 return 的函数任何价值。没有更好的方法来处理它。如今,有了 void return 类型,有更好的方法来处理它。然而,return 值通常很少引起人们的兴趣。您多久检查一次 printf() 或其朋友之一的 return 值?您多久使用一次 strcpy() 等人的 return 值?

C90 必须允许旧代码仍然 运行,所以它允许旧的 pre-standard 行为。 C99 收紧了规则——函数不再是隐式类型 int 并且必须在使用之前声明(使用显式 return 类型,可能 void)。