C EOF是否设置了errno?

C EOF是否设置了errno?,c,unix,system-calls,C,Unix,System Calls,我总是为系统调用的返回值而挣扎——它们太不一致了! 通常我检查它们是否为NULL或-1,然后调用perror。但是,对于fgets,手册页显示: gets()和fgets()在成功时返回s,在错误时或在未读取字符时出现文件结尾时返回NULL 这意味着返回值NULL不一定是错误-也可能是EOF。到达文件末尾时是否设置了errno?在这种情况下,我还能打电话给Peror吗 如果不是,那么,与EOF相比,判断调用是否返回错误的常用方法是什么。我想使用perror和空字符串表示错误,使用自定义字符串表示

我总是为系统调用的返回值而挣扎——它们太不一致了! 通常我检查它们是否为NULL或-1,然后调用
perror
。但是,对于
fgets
,手册页显示:

gets()
fgets()
在成功时返回s,在错误时或在未读取字符时出现文件结尾时返回NULL

这意味着返回值
NULL
不一定是错误-也可能是EOF。到达文件末尾时是否设置了errno?在这种情况下,我还能打电话给Peror吗


如果不是,那么,与EOF相比,判断调用是否返回错误的常用方法是什么。我想使用
perror
和空字符串表示错误,使用自定义字符串表示EOF。

使用
ferror
feof
区分错误和EOF。如果有错误的话,没有通用的方法来准确地找出错误是什么,但是你可以知道有错误

标准C
(f)get
(和
(f)getc
)不需要设置
errno
,尽管一致性库实现可以随意将
errno
设置为非零值


Posix确实要求
(f)获取{c,s}
设置
errno
读取错误,但这仅在确定存在读取错误后(通过调用
ferror
)才有帮助。同样重要的是要记住,库函数从不将
errno
设置为0,但即使没有错误发生,也可能将
errno
设置为非零值。因此,您不能测试
errno
来代替检查任何库函数的错误返回,包括
fgets
。由于文件结尾不是错误,
errno
可能不会在EOF上修改,所以在这种情况下它的值是没有意义的。

根据fputs自己的文档,是的,EOF设置了errno。手册页间接地推断了这一点,而不是直截了当地说出来,希望能加以修改。函数fputs返回一个整数,成功时为正,失败时为EOF。因此,错误处理FPUT的关键是设置一个代码块,在调用FPUT时检查其返回值。下面是我如何被教导处理fputs错误的一个片段

if (fputs(buffer, stdout) == EOF)
{
  fprintf(stderr, "fputs returned EOF: %s\n", strerror(errno));
  // .. and now do whatever cleanup you need to do.
  // or be lazy and exit(-1)
}
在这里,我将缓冲区的内容写入标准输出,并检查fputs是否返回EOF。EOF表示设置了错误代码,因此只要遵循FPUT手册页上的文档,就应该能够创建一组if语句来检查errno可以设置为的各种错误代码

(1) 什么是缓冲区?我在别处声明的一些字符数组

(2) fprintf做什么?它将输出打印到传入的文件描述符,这在本例中是标准错误(stderr…它像stdout一样打印到控制台,但对于错误)

(3) 什么是strerror?它是一个在string.h头中定义的函数,用于为传入的错误代码打印错误信息。它包含errno可以设置为的每个错误代码的信息。头文件string.h不应与strings.h混淆,后者是不包含strerror(3)的BSD linux头文件

编辑:好吧,我搞砸了。你在寻找关于FGET而不是FPUT的答案

要检查FGET上的错误,请执行以下操作

if (fgets(buffer, BUF_SIZE, myFile) == NULL)
{ 
  // print out error as a string to stderr
  fprintf(stderr, "fgets error occurred: %s\n", strerror(errno));
  // do cleanup
}
// special: you also need to check errno AFTER the if statement...
问题是,如果流变得不可读(这可能是由于权限或试图读取处于写入模式的内容),那么您在这方面得到错误的唯一方法就是。在网络的情况下,有可能在阅读过程中有什么东西切断你的连接,在这种情况下,你还需要检查FFIF if语句之后的错误代码。但如果出现问题,它将设置错误代码


至少如果手册页是正确的话。有关更多详细信息,请参阅linux手册页。唯一可以设置的错误代码是“我看不见这个东西”代码,它是errno==EBADF

@Xufeng:不,它直接从
文件
对象获取信息,以某种特定于实现的方式。@Xufeng:不太可能,因为
errno
尚未设置(至少不是由
ferror
(f)get
),因此,
perror
的结果充其量只是误导。你所能做的就是打印一些本地化版本的
I/O error
,但是
perror
也不会做得更好,即使设置了
errno
。哦,既然你说fgets没有设置errno,所以我做了一些研究,发现fgets一开始就不是一个系统调用@徐峰:是的,这是这里要记住的重要事情。系统调用在使用
errno
时是一致的。但本手册第2节中的功能仅为系统调用
gets
fgets
是标准C库函数,标准C库是可移植的,对unix特定接口的存在一无所知,如
errno
@JanHudec:standard C包含头文件
的定义,其中包括
errno
的定义:"... 它扩展为具有int类型和thread local storage duration的可修改左值,其值由多个库函数设置为正错误数。“其中一个函数是
strtod
,它也不是系统调用。注意:1)OP的帖子位于
fgets()
而不是
fputs()
.2)根据C11标准,
fputs()
errno
不起作用。可能它在*nix内起作用。@chux:C标准没有说
fputs()
errno
不起作用。它没有说它是否起作用。7.5p3:无论是否存在错误,
errno
的值可通过库函数调用设置为非零,前提是
errno
的使用未在本Interna中的函数描述中记录