我一直想知道为什么 C++ 标准库使用char
类型而不是类型来实例化 basic_[io]stream 及其所有变体unsigned char
。char
意味着(取决于它是否已签名)您可以对 get() 之类的操作进行上溢和下溢,这将导致所涉及的变量的实现定义值。另一个例子是当你想使用它的put
函数将一个未格式化的字节输出到 ostream 时。
有任何想法吗?
注意:我仍然不太相信。因此,如果您知道明确的答案,您仍然可以确实发布它。
可能我误解了这个问题,但是从 unsigned char 到 char 的转换不是未指定的,它依赖于实现(C++ 标准中的 4.7-3)。
C++ 中 1 字节字符的类型是“char”,而不是“unsigned char”。这为实现提供了更多的自由来在平台上做最好的事情(例如,标准机构可能认为存在有符号字节算术比无符号字节算术更快的 CPU,尽管这是我的猜测)。也是为了与 C 兼容。从 C++ 中消除这种存在不确定性的结果是 C# ;-)
鉴于存在“char”类型,我认为通常流使用它是有意义的,即使它的符号没有定义。因此,也许您的问题可以通过“为什么 C++ 不将 char 定义为无符号?”的答案来回答。
我一直是这样理解的:iostream
该类的目的是读取和/或写入字符流,如果您考虑一下,这些字符流是仅由计算机使用字符编码表示的抽象实体。C++ 标准极力避免限制字符编码,只说“声明为字符 ( char
) 的对象应足够大以存储实现的基本字符集的任何成员”,因为它不需要强制“实现基本字符集”来定义C++语言;标准可以将使用哪种字符编码的决定留给实现(编译器与 STL 实现一起),char
实现编写者可以选择单字节编码,例如ISO-8859-1,甚至可以选择双字节编码,例如UCS-2。没关系。只要一个char
对象“大到足以存储实现的基本字符集的任何成员”(请注意,这明确禁止可变长度编码),那么实现甚至可以选择一种以不兼容的方式表示基本拉丁语的编码任何常见的编码!
令人困惑的是char
,signed char
和unsigned char
类型在它们的名称中共享“char”,但重要的是要记住它与和char
不属于同一基本类型家族。属于有符号整数类型家族:signed char
unsigned char
signed char
有四种有符号整数类型:“signed char”、“short int”、“int”和“long int”。
并且unsigned char
属于无符号整数类型家族:
对于每个有符号整数类型,都存在一个对应的(但不同的)无符号整数类型:“unsigned char”、“unsigned short int”、“unsigned int”和“unsigned long int”……
char
、signed char
和类型之间的一个相似之处unsigned char
是“[它们] 占用相同的存储量并具有相同的对齐要求”。因此,您可以reinterpret_cast
从char *
tounsigned char *
来确定执行字符集中某个字符的数值。
要回答您的问题,STLchar
用作默认类型的原因是因为标准流用于读取和/或写入由char
对象表示的字符流,而不是整数(signed char
和unsigned char
)。char
对数值的使用是一种分离关注点的方法。
char 用于字符,unsigned char 用于原始数据字节,signed char 用于有符号数据。
标准没有指定是否使用有符号或无符号字符来实现 char - 它是特定于编译器的。它只指定“char”将“足以”在您的系统上保存字符——就像当时的字符一样,即没有 UNICODE。
对字符使用“char”是标准方法。使用 unsigned char 是一种 hack,尽管它会在大多数平台上匹配编译器对 char 的实现。
我认为这个评论很好地解释了这一点。去引用:
signed char 和 unsigned char 是算术整数类型,就像 int 和 unsigned int 一样。另一方面, char 明确旨在成为“I/O”类型,表示平台上一些不透明的、特定于系统的基本数据单元。我会本着这种精神使用它们。