标准C功能:检查-1或0?

Mat*_*ner 5 c c++ correctness conventions return-value

许多标准C和POSIX函数返回-1的错误,并0成功,例如truncate,fflush,msync等.

int ret = truncate("/some/file", 42);
Run Code Online (Sandbox Code Playgroud)

ret != -1或检查成功是否更好ret == 0?为什么?

我的想法

这是我的经验,大多数人检查错误情况(ret != -1),因为通常只有一个(考虑返回NULLEOF出错的函数).然而事后看来,人们可以看到这些功能可以从errno直接返回中受益(在哪里0被认为没有错误).

还担心函数会返回除0or -1之外的其他内容,或者稍后会添加其他返回值.在这些场景中,测试表示成功(ret == 0)的"最紧密"值的值是有意义的.

Update0

人们都知道这EOF是我的一个假设,通常被定义为-1.

Joh*_*ica 8

这取决于函数是C标准库函数还是POSIX函数.C函数没有统一的返回码标准,所以我会根据具体情况使用最有意义的测试.

另一方面,POSIX更加一致.几乎所有POSIX函数都被定义为返回-1,并提供更具体的错误代码errno.有些函数只返回0表示成功,而其他函数则有很多成功值.例如,open()返回文件描述符,read()返回读取的字节数等.

为了保持一致性,我喜欢在调用POSIX函数时始终使用相同的测试:不要测试成功,测试失败.今天在错误时返回-1的POSIX函数将始终返回-1,因此我将对所有这些函数使用两个检查之一:

if (ret == -1) {
    perror(...);
}

// or

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

(我更喜欢第一个,但第二个更普遍的不会打扰我.)

  • 第二个是在大多数架构上快一点点,因为通常有一个消极性的状态标志和使用它的条件分支. (3认同)

ssu*_*ube 3

在我看来,这实际上取决于您需要做什么以及返回值的范围。

接听具有一个成功值和多个失败值的呼叫。==通常,检查或!=检查成功的返回值比检查任何失败值更容易。在这种情况下,您将测试!= success是否需要记录并在失败时返回或抛出。

在一和一的通话中,所需的行为更为重要,因此我建议选择更具可读性的。如果您的代码需要对失败做出反应并可能返回失败,请检查== failure而不是!= success. 前者更具可读性,因为它需要一步思考,并且命名失败常数可能会有所帮助。

您可能还需要考虑哪个更有可能并首先处理,或者哪个在数值上更大或更小。

在您的情况下,两个函数共享一个成功代码并且具有不同的失败代码,它会落在看起来更可读的一个上。我同意== 0在这两种情况下进行测试似乎会更好,但这实际上取决于调用之间有多少代码。如果您有几十行,则可读性可能不会有太大差异。如果非常接近,您甚至可以将结果进行“或”运算,从而节省更多步骤。

  • +1:我喜欢这个。正如布尔变量和文件名应该是“正”断言,如“is_empty()”或“is_full()”而不是“not_empty()”、“cant_connect()” - 对我来说,将错误测试视为更直观明智`!= _success_` 测试,因为 `!=` 本身暗示了某种错误,就像 `== success` 读起来比 `!= failure` 更流畅。布尔逻辑更容易正确,无需额外的否定和双重否定。我更喜欢 `if (... &lt; 0)` 而不是 if `(... == -1)`:后者暗示了一些更违反直觉的东西,而第一个提出了“诚实”的问题。 (3认同)