我已经阅读了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
参数fputc
转换为unsigned char
。对于fgetc
,给出了类似的注意事项。
7.21.7.1.2:
fgetc
函数作为转换为int
的unsigned char
获得该字符。
还有ungetc
,fread
和fwrite
。
现在所有这些都暗示,在内部,面向字节的流是由unsigned char
表示的。
然而,从Linux内核的内部来看,文件似乎被认为是char
的流。我要说的一个原因是,运营 read
和write
回调分别得到了char __user *
和const char __user *
。
在glibc
的实现中,FILE
是在libio/libio.h
中定义的typedef
of struct _IO_FILE
。在这个struct
中,所有的读和写指针都是char *
。
在C++中,basic_ostream::write
函数以const char *
作为输入,并以类似的basic_istream::read
(但我对这个问题对C++不感兴趣)。
我的问题是,上面的引号是否意味着文件流应该作为unsigned char
**?的流被三分。如果是这样的话,为什么* glibc
和Linux内核使用**‘`char****? If not, why does the standard insist on converting the characters to** **
未签名字符’**?来实现它们?
发布于 2012-09-23 10:11:09
这真的不重要。标准在选定的地方使用未签名的字符,因为它允许在这些地方精确地表述:
fgetc
被指定返回一个转换为int的无符号字符,以便当它是EOF时,知道结果是正的或空的(因此在EOF和有效的char之间不可能出现混淆,这是在没有预先检查EOF的情况下,直接将fgetc的结果存储在一个字符中而导致错误的原因)。fputc
接受int并将其转换为无符号字符,因为此转换是很好地指定的。如果您不小心,不使用无符号字符的公式可能会使UB成为类似的序列
int c= fgetc(stdin);if (c != EOF) fputc(c,stdout);带有负号字符的字符。
发布于 2012-09-23 09:52:41
这真的不重要。一个CHAR_BIT
位长(limits.h
-通常是8位),不管它是否有签名。
这些函数与CHAR_BIT
位块一起工作,因此对于写入或读取过程来说,符号在这里并没有什么区别。
然后,您可以根据应用程序逻辑使用已签名或无符号的字符,方法是适当地转换结果。根据符号的不同,人工表示将是不同的,但是对于处理器来说,表示不会改变。仍然是字节。
发布于 2012-09-23 10:02:36
唯一可以直接观察到的(不检查源)是API返回的内容。它背后的任何东西都被黑匣子的抽象所掩盖,而不是你所关心的。
关于问题的另一部分:标准必须注意,有一个转换,因为参数/返回值是int
,流是字符序列。
https://stackoverflow.com/questions/12554696
复制相似问题