5

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

int ret = truncate("/some/file", 42);

ret != -1使用or检查是否成功是更好的做法ret == 0,为什么?

我的想法

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

还有人担心函数返回的不是0or -1,或者稍后会添加额外的返回值。在这些情况下,测试表明成功的“最紧密”值范围 ( ) 是有意义的ret == 0

更新0

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

4

9 回答 9

8

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

另一方面,POSIX 更加一致。几乎所有 POSIX 函数都被定义为返回 -1,并在errno. 一些函数简单地返回 0 表示成功,而另一些函数则有多个成功值。例如,open()返回文件描述符,read()返回读取的字节数等。

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

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

// or

if (ret < 0) {
    perror(...);
}

(我更喜欢第一个,但第二个更一般的并不会打扰我。)

于 2010-10-01T04:50:07.580 回答
3

比较 和 的手册页truncatefflush成功时都返回 0,但返回不同的错误值(截断 -> -1,fflush -> EOF)。所以我会检查0。

于 2010-10-01T04:45:03.520 回答
3

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

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

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

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

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

于 2010-10-01T04:53:40.190 回答
2

证书指南似乎更喜欢 '!= 0' 检查,因为在他们的许多示例代码片段中都是有效的。

于 2010-10-01T04:47:54.393 回答
2

始终检查手册页以获取返回码。

通常 0 表示成功,但也有例外,例如printf().

检查man 2 intro系统调用的 errnos 和错误代码。

于 2010-10-01T04:52:24.533 回答
2

无论你做什么,永远不要用

if (!ret) 

这很令人困惑,以后有人(包括您自己)会将其误读为失败的测试。通常最好使用显式测试。

于 2010-10-01T07:32:43.983 回答
1

如果定义是 0 表示成功,并且您想检查是否成功,那么您应该检查 0 的等价性。(除了剪切可读性之外没有其他原因)

于 2010-10-01T04:46:32.817 回答
1

对于大多数 POSIX API 函数,负值是错误。所以我会用if (ret < 0).

于 2010-10-01T04:47:32.563 回答
0

我的经验法则是,像这样的函数通过返回值返回错误代码(或者只是是否发生错误)。所以,对我来说,返回值 0 意味着没有任何东西可以返回并且没有发生错误是有道理的。因此,如果我想测试函数是否成功,我只检查返回值是否为 0,如果不是,则只检查错误值是什么并相应地处理它。

于 2010-10-01T04:55:32.043 回答