fgets的n参数的含义是否随时间而变化?

时间:2017-01-26 09:43:03

标签: c fgets

Apple developer documentation州:

  

fgets 的安全说明:尽管fgets功能提供了读取有限数量数据的功能,但在使用时必须小心。与“更安全”列中的其他函数一样,fgets始终终止字符串。但是,与该列中的其他函数不同,它需要读取最大字节数,而不是缓冲区大小。

最后一句话对我来说听起来不对。为了比较,这里是what POSIX says

  

fgets()函数应从流中读取字节到s指向的数组,直到读取n-1个字节,或者读取<newline>并将其传输到{{ 1}},或遇到文件结束条件。在读入数组的最后一个字节后,应立即写入空字节。

以下是an ISO C draft from 2005 says

  

s函数从fgets指向的流中将n指定的字符数最多读取一个小于stream指向的数组。在换行符(保留)或文件结束后不会读取其他字符。在读入数组的最后一个字符后立即写入空字符。

FreeBSD手册页与C标准和POSIX相同。

这让我觉得Apple文档显然是错误的。最简单的解释是,Apple发表这篇文章时并不知道。但是虽然很简单,但这个假设对我来说并不合理。

还有其他原因导致Apple可能偏离C标准的措辞吗?

2 个答案:

答案 0 :(得分:2)

甚至早期(20世纪70年代早期)fgets()版本指定n是缓冲区大小,缓冲区将以'\0'终止。

Kernighan和Ritchie在他们的所有书籍和文档中都正确地反映了这一点。

然而,许多介绍性文章的作者(我不会尝试命名,因为我确定我会错过一些,并且所有人都应该同样感到尴尬)记录了这一点。可以将n个字符写入缓冲区,并且在某些情况下可能会删除尾随的'\0'

答案 1 :(得分:1)

fgets函数最多读取大小减去文件中的一个字节。如果错误的值作为缓冲区大小传递,则fgets可能会写出越界。

因此,您显示的Apple文档中的引用是正确的,因为该值与从文件中读取的字节数更相关。但另一方面,任何普通代码在下降fgets时都会使用实际的缓冲区大小。如果该数字是从用户输入的,则应在使用前进行验证。

另一方面,文件继续说明(感谢Sander De Dycker的说明)

  

实际上,这意味着您必须始终传递一个小于缓冲区大小的大小值,以便为空终止留出空间。如果不这样做,fgets函数将尽可能地终止缓冲区末尾的字符串,可能会覆盖其后的任何字节数据。

这个是错误的。传递给fgets的size参数始终包含字符串终止符。至少根据C标准。