我已阅读C11标准,第7.21节,其中描述了<stdio.h>
。该标准首先将流描述为:
7.21.2.2:
文本流是一个有序的字符序列......
7.21.2.3:
二进制流是一个有序的字符序列......
其中没有指定流字符的类型(因为这取决于方向)。它后来说:
7.21.3.12:
...字节输出函数将字符写入流,就好像通过连续调用fputc函数一样。
来自fputc
(7.21.7.3.2):
fputc
函数将c
指定的字符(转换为unsigned char
)写入stream
指向的输出流...
这表示int c
的{{1}}参数在写入流之前会转换为fputc
。类似的注释是unsigned char
:
7.21.7.1.2:
fgetc
函数将该字符转换为fgetc
转换为unsigned char
和int
,ungetc
和fread
。
现在所有提示在内部,面向字节的流由fwrite
s表示。
然而,看看Linux内核的内部,似乎文件被认为是unsigned char
的流。我这样说的一个原因是file_operations char
和read
回调分别得到write
和char __user *
。
在const char __user *
的实施中,glibc
是FILE
typedef
的{{1}},在struct _IO_FILE
中定义。在此libio/libio.h
中,所有读写指针都是struct
。
在C ++中,basic_ostream::write
函数将char *
作为输入,类似const char *
(但在这个问题中我对C ++不感兴趣)。
我的问题是,上面的引号是否意味着FILE流应该作为basic_istream::read
的流进行威胁?如果是这样,为什么unsigned char
和Linux内核用glibc
实现它们?如果没有,为什么标准会坚持将字符转换为char *
?
答案 0 :(得分:4)
这并不重要。该标准在某些选定的地方使用无符号字符,因为它允许在这些地方进行精确配方:
fgetc
被指定为返回一个转换为int的unsigned char,以便在EOF时知道结果是正数或null除外(因此EOF和a之间不存在混淆)有效的char,混乱是导致错误的原因,当一个商店直接存储fgetc的结果而没有预先检查EOF时。
fputc
取一个int并将其转换为unsigned char,因为已明确指定了此转换。如果你不小心,不使用unsigned char的公式可能会使UB成为像
int c = fgetc(stdin);
if (c != EOF)
fputc(c, stdout);
带有负面字符的签名字符。
答案 1 :(得分:2)
这并不重要。 char
CHAR_BIT
位长(limits.h
- 通常为8位),无论是否已签名。
这些函数与CHAR_BIT
位块一起使用,因此对于写入或读取过程,符号在这里没有区别。
然后,您可以通过适当地转换结果来使用有符号或无符号字符,具体取决于您的应用程序逻辑。人类表示将根据符号而不同,但对于处理器,表示不会改变。它仍然是字节。
答案 2 :(得分:1)
唯一可以直接观察(不检查源)的是API返回的内容。无论背后是什么,都被黑匣子抽象所隐藏,不应该是你的关注。
关于问题的其他部分:标准有要注意,有转换,因为参数/返回值是int
,而流是字符序列。< / p>