在 <char>sizeof(int) == 1 的平台中如何编码 char_traits::eof() ?

How is char_traits<char>::eof() encoded in platforms where sizeof(int) == 1?

本文关键字:char 编码 何编码 traits eof sizeof gt lt int 平台      更新时间:2023-10-16

我在C++标准中找到了这些摘录(引自N4687,但它可能永远存在(:

[字符特征.类型定义]

对于某个字符容器类型char_type,相关的容器类型INT_T应为 类型或类,可以表示从相应的char_type值转换的所有有效字符,以及文件结束值eof()

[字符特征要求]

表达式:X::eof()

类型:X::int_type

返回:一个值e使得X::eq_int_type(e,X::to_int_type(c))对于所有值cfalse

表达式:X::eq_int_type(e,f)

类型:bool

返回:对于所有cdX::eq(c,d)等于X::eq_int_type(X::to_int_type(c), X::to_int_type(d))(...

cd表示类型CharT的值;(...);ef表示类型X::int_type的值

[字符.特征.专业化.字符]

using char_type = char;
using int_type = int;

[基础.基础]

普通charsigned charunsigned char是三种不同的类型,统称为窄字符类型。(...)charsigned charunsigned char占用相同的存储量并具有相同的对齐要求 (...(对于窄字符类型,对象表示形式的所有位都参与值表示形式。(...)对于无符号窄字符类型,值表示形式的每个可能的位模式都表示一个不同的数字。

有五种标准有符号整数类型:"signed char"、"short int"、"int"、"long int"和"long long int"。在此列表中,每种类型提供的存储量至少与列表中前面的存储量相同。

我在周围的文本中没有发现任何阻止sizeof(int) == 1的东西。在大多数现代平台中,sizeof(int)显然不是这种情况,其中 是 4 或 8,但明确用作示例,例如在 cpp首选项中:

注意:这允许极端情况,即字节大小为 64 位,所有类型(包括 char(均为 64 位宽,sizeof 为每种类型返回 1。

问题

如果intchar一样大,该标准没有为前者的任何对象表示留出太多空间,这些对象表示将不等于后者的所有值(通过to_int_type(进行比较,只留下一些极端情况(如signed char中存在的负零,但在int中映射到INT_MIN(不太可能在硬件中有效实现。此外,对于 P0907,似乎即使signed char也不允许任何两个不同的位字符串表示相等的值,从而迫使它为 2^(bitsize( 不同的值,int也是如此,并关闭了所有可能的漏洞。

在这样的平台上,如何符合std::char_traits<char>的要求?我们是否有此类平台和相应实现的真实示例?

例如,假设我们有一个平台,其中char是有符号的,长度为32位,int也是如此。使用以下定义可以满足所有要求,其中Xstd::char_traits<char>

  • X::eqX::eq_int是简单的相等比较;
  • X::to_char_type返回其参数的值;
  • X::eof返回 -1,并且
  • X::to_int_type(c)c,除非c是-1,在这种情况下它是-2。

-1 到 -2 的映射保证了所有cX::eq_int_type(X::eof(), X::to_int_type(c))为假,这是根据 C++20 表 69 对X::eof的要求。

这可能对应于 -1 和 -2(甚至可能是所有负数(是"无效"字符值的实现,它们存储在char中是完全合法的,但从文件中读取永远不会产生具有此类值的字节。当然,没有什么能阻止您编写生成此类"无效"值的自定义流缓冲区,只要您愿意接受无法区分"下一个字符是 -1"和"我们在流的末尾"这一事实。

此实现唯一可能的问题是,对X::to_char_type(e)的要求是它等于

如果对于某些cX::eq_int_type(e,X::to_int_type(c))truec;否则是一些未指定的值。

这可以理解为暗示,如果存在任何此类c,那么它是独一无二的。当e为 -2 时,将违反该规定,因为此处c可以是 -1 或 -2。

如果我们假设唯一性是必需的,那么我认为没有任何可能的解决方案。