检查读写系统调用的返回值的最佳方法是什么?

时间:2019-11-13 08:43:24

标签: c coding-style

我有兴趣找出在Linux上从读写系统调用中检查返回值的最佳方法。根据手册页,例如,写:

  

成功完成后,write()和pwrite()将返回   实际写入与fildes关联的文件的字节数。   此数字不得大于nbyte。否则,-1为   返回并设置errno以指示错误。

供阅读:

  

成功后,返回读取的字节数(零表示结束   的文件名),文件位置按此数字前进。它不是   如果此数目小于请求的字节数,则发生错误;   例如,这可能是因为实际可用的字节较少   现在(也许是因为我们接近文件结尾,或者是因为   正在从管道或终端读取),或者因为read()为   被信号打断。错误时,返回-1,并设置errno   适当地。在这种情况下,未指定文件是否   位置(如果有)发生变化。

这让我感到奇怪:

if (ret < 0) {
    // see strerror
}

if (ret == -1) {
    // see strerror
}

走哪条路,为什么?从手册的角度看,从功能的角度来看,这些手册页完全相同。这样对吗?我猜测的唯一区别是,第一条语句应使用比较器,这将需要更多资源。这个假设对吗?请与我分享您的想法。谢谢

2 个答案:

答案 0 :(得分:1)

首先,我将使用gcc 9.2(x86-64)并着眼于性能来进行研究:

#include <stdio.h>

int main(int argc, char **args, char **env) {
   if (argc < 0) {
       printf("ERROR!");
   }

   return 0;
}

会生成类似

的内容
.LC0:
        .string "ERROR!"
main:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 32
        mov     DWORD PTR [rbp-4], edi
        mov     QWORD PTR [rbp-16], rsi
        mov     QWORD PTR [rbp-24], rdx
        cmp     DWORD PTR [rbp-4], 0
        jns     .L2
        mov     edi, OFFSET FLAT:.LC0
        mov     eax, 0
        call    printf
.L2:
        mov     eax, 0
        leave
        ret

#include <stdio.h>

int main(int argc, char **args, char **env) {
   if (argc == -1) {
       printf("ERROR!");
   }

   return 0;
}

产生

.LC0:
        .string "ERROR!"
main:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 32
        mov     DWORD PTR [rbp-4], edi
        mov     QWORD PTR [rbp-16], rsi
        mov     QWORD PTR [rbp-24], rdx
        cmp     DWORD PTR [rbp-4], -1
        jne     .L2
        mov     edi, OFFSET FLAT:.LC0
        mov     eax, 0
        call    printf
.L2:
        mov     eax, 0
        leave
        ret

因此在性能方面没有任何区别。具有此编译器和体系结构。

其他任何事情都是个人的看法。我个人会选择“ <0” ...只是因为它捕获了所有内容。

答案 1 :(得分:0)

Maxine在IMO中的评论中回答了样式问题。

效率也更好,特别是如果编译器更积极地优化代码

https://godbolt.org/z/MrTdqX