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规范没有提到当它不读取任何数据时也不做什么,也没有写任何数据到s
when(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 次 |
最近记录: |