C检查标准库中的错误(ret <0 vs ret == -1)

use*_*392 11 c posix

我经常看到代码通过测试小于零而不是显式定义来检查来自POSIX函数的错误,并且通常只使用错误代码-1.那是

ret = function();
if (ret < 0) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

VS

ret = function();
if (ret == -1) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

第一次练习有什么目的吗?在某些体系结构上比0与-1比较的速度要快吗?如果现在定义的唯一错误代码是-1,C或POSIX标准是否可以保证第一个替代方案将来不会中断?如果没有,是否应该被视为不良做法?(我想大多数函数不太可能以这种方式改变,导致很多已编写的代码破坏?).

编辑:使问题更清楚:我只谈论专门返回-1的函数作为标准定义的错误代码.我知道有一些没有.我在很多地方看到了<0检查这些函数而不是== -1.因此问题.

AnT*_*AnT 8

首先,一些函数只有一个错误代码,有些函数有更多.例如,pthread_createPOSIX函数可以返回多个错误代码.当我不关心具体的错误代码时,我也不想关心它们有多少.在这种情况下,检查负回报只是一种可靠的通用免维护方法,涵盖所有情况.另外,POSIX规范中的错误通常根据清单常数来描述,而不是根据特定数值来描述.

其次,我不确定POSIX究竟对于现有函数的错误返回的可扩展性是什么,但我自然希望在我的代码中预期这种可能性.

第三,通常,在许多(如果不是大多数或所有)处理器上检查"否定"值比检查特定值更有效.许多CPU都有一个专用的CPU状态标志,用于指示否定结果.这意味着对负值的测试不必涉及文字操作数.例如,在x86平台上测试否定性不必涉及与文字的比较0.与特定值进行比较通常需要将该特定值嵌入到机器指令中,从而导致指令变慢.然而,在任何情况下,"特殊"的值,比如0,-1,1等等,都可以使用更聪明和有效的技术测试.因此,我怀疑所讨论的比较是出于性能原因而采用的方式.

  • 我说'通常'.我没有概括关于所有函数的问题,这些函数在出错时仅返回-1.也许应该让它更清晰.谢谢你的回答. (2认同)

Chr*_*odd 7

这主要是历史事故.曾经有(pre-POSIX)类UNIX系统在错误而不是-1时返回-errno,因此您不必使用全局errno变量.因此检查<0将适用于此类系统.

您仍然可以在Linux中看到此历史记录 - 系统调用返回-errno,C库检查范围[-4096 ..- 1]中的值.如果返回值在该范围内,则库否定它并将其存储在errno(内核不知道)中,然后返回-1.