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

时间:2009-12-04 18:16:39

标签: c return-value errno

另一个简单的例子:

if (wpa_s->mlme.ssid_len == 0)
    return -EINVAL;

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

4 个答案:

答案 0 :(得分:17)

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

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

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

答案 1 :(得分:14)

这基本上就是原因。很多函数都有很多“好”的正结果,所以留下了错误代码的负值。

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

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

答案 2 :(得分:7)

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

然而,标准惯例与您的公式略有不同。

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

这导致了一种通用范例,其中>= 0表示良好< 0表示错误。这些都不是一成不变的。

顺便说一句,这可能被归类为 sentinel pattern ,您可以将其称为哨兵返回。它实际上是一种组合一个标记“值”和一个错误代码,并且比在一个地方返回错误代码和在另一个地方返回错误代码的sentinel值更容易键入并更容易进行线程安全。

Wikipedia reports that a sentinel value用于终止循环,但我认为函数返回将是一个更常见的实例。没有人正是这些定义的精确负责人。

答案 3 :(得分:1)

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

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

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

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

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

NULL if x <= 0x8000(0到0x8000为真)

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

You can see this happening in Linux's err.h file.