【发布时间】:2012-09-23 17:49:19
【问题描述】:
我已通读 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指向的输出流...
这表示fputc 的int c 参数在写入流之前转换为unsigned char。 fgetc 也有类似的注释:
7.21.7.1.2:
fgetc函数将该字符作为unsigned char转换为int
和ungetc、fread 和fwrite。
现在这一切都暗示在内部,面向字节的流由unsigned chars 表示。
但是,查看 Linux 内核的内部结构,文件似乎被视为char 的流。我这么说的一个原因是 file_operations read 和 write 回调分别得到 char __user * 和 const char __user *。
在glibc的实现中,FILE是struct _IO_FILE的typedef,在libio/libio.h中定义。同样在这个struct中,所有的读写指针都是char *。
在 C++ 中,basic_ostream::write 函数以 const char * 作为输入,同样以 basic_istream::read 为输入(但我对这个问题中的 C++ 不感兴趣)。
我的问题是,上面的引用是否暗示 FILE 流应该作为unsigned char 的流受到威胁?如果是这样,为什么glibc 和Linux 内核用char * 来实现它们?如果不是,为什么标准坚持将字符转换为unsigned char?
【问题讨论】:
-
fgetc的可能返回之一是错误代码(形式为EOF)。为了将错误代码与任何有效字符区分开来,标准将字符转换为unsigned char,然后转换为int。所以绝对没有办法将EOF解释为有效字符或任何有效字符作为错误代码。 -
@pmg,这是一个很好的观点。对于
fgetc,这是有道理的,因为例如-1作为字符将返回为255。对于fputc或ungetc,它们从int转换为unsigned char,但是我看不到任何好处。我的意思是,如果您将它们存储为char,那么char c = (unsigned char)i和char c = i(i是int输入)是相等的,不是吗? -
Simmetry 是追求的好特性:)
-
@pmg,我完全同意那个!