面向字节的FILE流是否包含`char`s或`unsigned char`s?

时间:2012-09-23 17:49:20

标签: c stdio

我已阅读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

intungetcfread

现在所有提示在内部,面向字节的流由fwrite s表示。

然而,看看Linux内核的内部,似乎文件被认为是unsigned char的流。我这样说的一个原因是file_operations charread回调分别得到writechar __user *

const char __user *的实施中,glibcFILE 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 *

3 个答案:

答案 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>