【问题标题】:Error in the systemcalls C11 for do file i/o用于执行文件 i/o 的系统调用 C11 中的错误
【发布时间】:2021-08-11 14:40:31
【问题描述】:

您好,我在 Linux WSL Debian 上,我有以下代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

int main(int argc, char *argv[]) {
    int fd = open("file.dat", O_RDONLY | O_WRONLY);
    write(fd, "ciao", strlen("ciao"));
    close(fd);
}

为什么不工作?

【问题讨论】:

  • 错误是这样的:main.c:在函数'main'中:main.c:10:5:警告:函数'write'的隐式声明;您指的是 “fwrite” 吗? [-Wimplicit-function-declaration] write(fd,"ciao",strlen("ciao")); ^~~~~ fwrite main.c:11:5: 警告:函数‘close’的隐式声明;您指的是 “pclose” 吗? [-Wimplicit-function-declaration] close(fd); ^~~~~
  • 如果您需要添加更多详细信息,请将它们放在问题中,而不是评论中。
  • @Cfanlover 跟进 Barmar 的评论:您知道您可以编辑您的问题吗?标签下的灰色小字“编辑”是一个按钮。是的,这是糟糕的 UI 设计,抱歉。

标签: c linux file-io system-calls windows-subsystem-for-linux


【解决方案1】:

您需要标头&lt;unistd.h&gt; 来获取write()close() 的声明。您需要的唯一其他标头是&lt;fcntl.h&gt; 用于open()

我还保留了&lt;stdio.h&gt;,因此如果open() 失败,我可以使用perror()

由于您只是在写入文件,因此在打开模式下不需要O_RDONLY。如果你想读写,你应该改用O_RDWR。这三个标志是互斥的。

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>

int main(int argc, char* argv[]) {
    int fd=open("file.dat",O_WRONLY);
    if (fd < 0) {
        perror("open failed");
        return 1;
    }
    write(fd,"ciao",strlen("ciao"));
    close(fd);
}

请注意,如果文件尚不存在,则不会创建该文件。如果需要,您需要添加 O_CREAT 标志和另一个参数,其中包含创建文件时应授予的权限。

【讨论】:

  • 如果文件不存在,使用O_WRONLY 打开会失败。
【解决方案2】:

许多错误:

  • 必须包含unistd.h 才能声明write
  • O_RDONLYO_WRONLY(和 O_RDWR)是互斥的。如果你想打开一个文件进行读写你必须使用O_RDWR。由于您实际上并没有从文件中读取,因此您应该单独使用 O_WRONLY
  • 想要使用O_WRONLY 而不使用O_CREATO_APPENDO_EXCLO_TRUNC 中的一个(正好是一个;这三个也是互斥的)是非常罕见的。假设您确实需要 O_CREAT,您还必须提供第三个参数,它应该是八进制常量 0666,除非您有特定理由使用其他值。
  • write(fd, "ciao", strlen("ciao")) 应该是 write(fd, "ciao\n", strlen("ciao\n")) 除非您有特定原因要创建最后一行不完整的文本文件。
  • 因为您正在写入文件,所以您需要检查openwriteclose 调用中的所有 个错误。 (close 可能失败的事实是其规范中的一个错误,但我们永远坚持这一事实。对于打开以供阅读的文件,忽略 close 中的错误是安全的,但是不写。)

还有一些样式更正:

  • 所示代码需要unistd.hfcntl.hstring.h;它应该还包括stdio.h,因为它应该也调用perror。不应包含任何其他标题(除非这是从更大的程序中删除的)。
  • main 声明为int main(void),除非您实际上要使用argcargv
  • 不要使用C99许可证掉到main的末尾; main 的最后一行应该是 return 0;
  • 由于历史原因,在 C 中,函数定义的左大括号应始终单独放置在一行上,即使所有其他左大括号都与其父控件“拥抱”流结构。

【讨论】:

    猜你喜欢
    • 2014-11-26
    • 2013-04-14
    • 1970-01-01
    • 2015-06-03
    • 1970-01-01
    • 2017-08-18
    • 1970-01-01
    • 2012-06-09
    • 1970-01-01
    相关资源
    最近更新 更多