chu*_*ica 11 c fgets language-lawyer
在单元测试中包含一个函数fgets(),当缓冲区大小时遇到意外结果n < 2.显然这样的缓冲区大小是愚蠢的,但测试正在探索极端情况.
简化代码:
#include <error.h>
#include <stdio.h>
void test_fgets(char * restrict s, int n) {
FILE *stream = stdin;
s[0] = 42;
printf("< s:%p n:%d stream:%p\n", s, n, stream);
char *retval = fgets(s, n, stream);
printf("> errno:%d feof:%d ferror:%d retval:%p s[0]:%d\n\n",
errno, feof(stream), ferror(stream), retval, s[0]);
}
int main(void) {
char s[100];
test_fgets(s, sizeof s); // Entered "123\n" and works as expected
test_fgets(s, 1); // fgets() --> NULL, feof() --> 0, ferror() --> 0
test_fgets(s, 0); // Same as above
return 0;
}
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是,fgets()收益NULL和既不 feof()也不ferror()是1.
下面的C规范似乎对这种罕见的情况保持沉默.
问题:
NULL,而不设置feof(),也不ferror()合规行为?n是1或小于1,它会有所不同吗?平台:gcc版本4.5.3目标:i686-pc-cygwin
这是C11标准的摘要,重点是我的:
7.21.7.2
fgets功能的与fgets函数读取比指定的字符数少至多一个Ñ [...]
如果成功,fgets函数返回s.如果遇到文件结尾且没有字符读入数组,则数组的内容保持不变,并返回空指针.如果在操作期间发生读取错误,则数组内容是不确定的,并返回空指针.
相关文章
如何在fgets中使用feof和ferror(C中的minishell)
在C(Seg-Fault和ferror)中创建shell的问题
fputs(),fgets(),ferror()问题和C++等价物
返回fgets()的值
[编辑]评论答案
@Shafik Yaghmour很好地介绍了整个问题:因为C规范没有提到当它不读取任何数据时也不做什么,也没有写任何数据到swhen(n <= 0)时,它是Undefined Behavior.所以任何合理的响应都应该是可以接受的,比如返回NULL,设置无标志,单独留下缓冲区.
至于应该发生什么时n==1,@ Oliver Matthews的回答和@Matt McNabb的评论表明C规格缺乏清晰度,考虑到缓冲区n == 1.C规范似乎倾向于缓冲区n == 1应该返回缓冲区指针s[0] == '\0',但是不够明确.
在新版本的 中,行为有所不同glibc, for n == 1,它返回s表示成功,这不是对7.19.7.2 fgets 函数第2段的无理阅读,其中说(在 C99 和 C11 中都是相同的,强调我的):
\n\n\nchar *fgets(char * 限制 s, int n , FILE * 限制流);
\n\nfgets 函数从stream 指向的流中最多读取比n \n 指定的字符数少1 的字符到s 指向的数组中。在换行符(保留)之后或文件结束符之后不会读取其他\n 字符。在读入数组的最后一个字符之后立即写入一个空字符。
\n
不是很有用,但不违反标准中所说的任何内容,它最多会读取0字符并以空终止。因此,您看到的结果看起来像是在后续版本中修复的错误glibc。它显然也不是文件结尾,也不是第3段中所述的读取错误:
\n\n\n[...]如果遇到文件结尾并且没有字符读入数组,则数组的内容保持不变并返回空指针。如果操作过程中发生读取错误,则数组内容不确定并返回空指针。
\n
就最终情况而言,n == 0这看起来只是未定义的行为。C99标准草案4. Conformance第2段说(重点是我的):
\n\n\n如果 \xe2\x80\x98\xe2\x80\x98shall\xe2\x80\x99\xe2\x80\x99 或 \xe2\x80\x98\xe2\x80\x98shall not\xe2\x80\x99\xe2\x80 \x99 违反了约束之外出现的要求,行为未定义。未定义的行为在本国际标准中另外通过文字 \xe2\x80\x98\xe2\x80\x98undefinedbehavior\xe2\x80\x99\xe2\x80\x99或通过省略任何明确的行为定义来表示。这三者的侧重点没有区别;它们都描述了未定义的\xe2\x80\x98\xe2\x80\x98行为\xe2\x80\x99\xe2\x80\x99。
\n
C11 中的措辞相同。最多无法读取-1个字符,并且它既不是文件结束也不是读取错误。所以我们对这种情况下的行为没有明确的定义。看起来像是一个缺陷,但我找不到任何涵盖此问题的缺陷报告。
\n| 归档时间: |
|
| 查看次数: |
1607 次 |
| 最近记录: |