为什么要回到负面的错误? (例如,返回-EIO)
另一个简单例子:
if (wpa_s->mlme.ssid_len == 0) return -EINVAL;
为什么一元减? 对于在成功时返回> 0且在失败时返回<(=)0的函数(通常)是否这样做了,还是有其他原因?
这基本上就是原因。 许多函数都有很多“好的”正结果,因此会为错误代码留下负值。
C / POSIX错误代码有点“历史性增长”,因此尝试将太多的押韵或理由归于它们没有多大意义。
许多现代语言都会抛出错误exception,这样他们就不必劫持错误代码可能的响应范围。 当然,无论如何都需要权衡利弊。
首先,这不是真正的C事。 你正在寻找一个用C语言编写的函数。 任何语言都可以使用相同的约定。
回到我原来的Unix时代,有一种惯例,0表示成功,正数表示小问题,负数表示某种失败。 因此,还有一种if (foo() >= 0) { /* success of a sort */ }
的约定。
这无疑与Unix进程返回代码有关,其中0表示成功。
您的理解大致正确。 明显的解释是正确的解释。
但是,标准惯例与您的公式略有不同。
在Unix中,一个程序退出0状态测试为真或成功的CLI级实用程序,如shell。 在库中, -1
通常是错误返回。
这导致了一般范式,其中>= 0
表示良好 , < 0
表示错误。 这些都不是一成不变的。
顺便说一句,这可能被归类为哨兵模式 ,你可以称之为哨兵回归。 它实际上是一个标记“值”和错误代码的组合,并且比在一个地方返回错误代码和在另一个地方返回错误的sentinel值更容易键入并更容易创建线程安全。
维基百科报告说,一个sentinel值用于终止循环,但我认为函数返回将是一个更常见的实例。 没有人正是这些定义的精确负责人。
从优化的角度来看,使用负数允许基于Unix的内核仅使用一个比较而不是两个来检查错误代码。
内核中的函数经常返回错误代码来代替指针。 这意味着错误代码不能与有效指针地址重叠,因此它们基本上必须是最低无符号值(>= 0)
或最高无符号值(<= unsigned max)
。
检查NULL
和错误代码的指针值是非常常见的操作,因此优化它们是有意义的。
通常,底值< 0x8000
为NULL
,顶值为错误代码(请记住-1
存储为0xff...ff
,最大可能的无符号值)。
这意味着您可以使用一个比较来检查每个:
如果x <= 0x8000
则为NULL
(对于0到0x8000,则为true)
ERRNO
如果x >= (unsigned long)(-MAX_ERRNO)
( x >= (unsigned long)(-MAX_ERRNO)
(对于-1到-MAX_ERRNO,则为真)
您可以在Linux的err.h文件中看到这种情况。