以下计划:
#include <stdio.h>
int main()
{
char s[10] = "";
fprintf(stdout, "%s", "hello");
fscanf(stdout, "%6s", s);
perror(NULL);
}
输出Bad file descriptor
。但是C11 draft standard的第7.21节似乎没有说明是否允许将stdout
传递给fscanf
。这是未定义的行为吗?明确(给出标准引用)或暗示(通过省略)?
答案 0 :(得分:4)
规范(ISO / IEC 9899:2011(E),§7.21)实际上没有提到对传递给输出函数的输入流或传递给输入函数的输出流的任何限制。规范中唯一的限制是传递给getFullPath()
的流必须是输出流。
答案 1 :(得分:2)
§4/ 2(引用WG14 N1570):
本国际上另有说明未定义的行为 标准用“未定义的行为”或“遗漏任何行为” 行为的明确定义。
§7.21.3/ 11
字节输入函数从流中读取字符,就像是 连续调用
fgetc
函数。
(fscanf
是字节输入函数;§7.2.1/ 5)。
§7.21.7.1:
fgetc
功能<强>概要强>
#include <stdio.h> int fgetc(FILE *stream);
<强>描述强>
2 如果指向输入流的文件结束指示符 未设置到
stream
,并且存在下一个字符fgetc
function将该字符转换为unsigned char
转换为int
并提升相关文件位置指示器 流(如果已定义)。<强>返回强>
3 如果设置了流的文件结束指示符,或者如果设置了 流位于文件结尾,即流的文件结束指示符 已设置,
fgetc
函数返回EOF
。否则,fgetc
function返回指向的输入流中的下一个字符 按stream
。如果发生读取错误,则为错误指示 设置了流,fgetc函数返回EOF
。 [脚注省略]
fgetc
的规范反复说“stream
指向的输入流”;在我看来,这可以通过两种方式阅读:要么隐含要求stream
指向输入流,要么标准省略指定stream
未指向任何行为时输入流。
在第一种情况下,将非输入流传递给fgetc
违反了该要求并且是未定义的行为(另见§7.1.4/ 1;有人可能认为这算作“域外的值”功能“);在第二种情况下,通过省略将非输入流传递给fgetc
是未定义的行为,因为该标准没有说明fgetc
在这种情况下的行为。所以我认为fgetc(not_an_input_stream)
会导致未定义的行为。
如果fgetc(not_an_input_stream)
是未定义的行为,那么fscanf(not_an_input_stream, /*...*/)
也是如此,因为后者被指定为通过调用前者来读取字符。