为什么要回到负面的错误?(例如,返回-EIO)

exs*_*ape 25 c errno return-value

另一个简单例子:

if (wpa_s->mlme.ssid_len == 0)
    return -EINVAL;
Run Code Online (Sandbox Code Playgroud)

为什么一元减去?对于在成功时返回> 0且在失败时返回<(=)0的函数,这(通常)是否完成,还是有其他原因?

Dav*_*ley 18

首先,这不是一个真正的C事物.你正在寻找一个用C编写的函数用于某种目的.任何语言都可以使用相同的约定.

回到我原来的Unix时代,有一种惯例,0表示成功,正数表示小问题,负数表示某种失败.因此,还有一种惯例if (foo() >= 0) { /* success of a sort */ }.

这无疑与Unix进程返回代码有关,其中0表示成功.


Car*_*icz 14

这基本上就是原因.许多函数都有很多"好的"正结果,因此会为错误代码留下负值.

C/POSIX错误代码有点"历史性增长",因此尝试将太多的押韵或理由归于它们没有多大意义.

许多现代语言都会抛出错误异常,这样他们就不必劫持错误代码的部分可能响应范围.当然,无论如何都需要权衡利弊.

  • 至少在过去,将0定义为成功,将积极定义为成功的问题,将消极定义为不成功 - 至少在我的旧Unix时代. (8认同)

Dig*_*oss 7

您的理解大致正确.明显的解释是正确的解释.

但是,标准惯例与您的公式略有不同.

在Unix中,一个程序退出,其中0状态测试为真实成功的CLI级别实用程序,如shell.在库中,-1通常是错误返回.

这导致了一种通用范例,>= 0意味着良好并且< 0意味着错误. 这一切都不是一成不变的.

顺便说一句,这可能被归类为哨兵模式,你可以称之为哨兵回归.它实际上是一个标记"值"和错误代码的组合,并且比在一个地方返回错误代码和在另一个地方返回错误的sentinel值更容易键入并更容易进行线程安全.

维基百科报告说,一个sentinel值用于终止循环,但我认为函数返回将是一个更常见的实例.没有人正是这些定义的精确负责人.


ves*_*len 6

从优化的角度来看,使用负数允许基于 Unix 的内核仅使用一个而不是两个比较来检查错误代码。

内核中的函数经常返回错误代码而不是指针。这意味着错误代码不能与有效的指针地址重叠,因此它们基本上必须是最低的无符号值(>= 0)或最高的值(<= unsigned max)

检查NULL错误代码的指针值是非常常见的操作,因此优化它们是有意义的。

通常,底部值< 0x8000NULL错误代码,顶部值是错误代码(请记住,-1存储为0xff...ff,最大可能的无符号值)。

这意味着您可以使用一个比较来检查每个:

NULLif x <= 0x8000(0 到 0x8000 为真)

ERRNO如果x >= (unsigned long)(-MAX_ERRNO)(对于 -1 到 -MAX_ERRNO 为真)

您可以在 Linux 的 err.h 文件中看到这种情况。