有点晚了,但我无法抗拒这一点。预测未来是艰难的。预测计算机的未来对你的代码来说可能比过早的优化更危险。
简短答案
虽然我以 9 位系统如何处理 8 位字节的可移植性来结束这篇文章,但这种经历也让我相信 9 位字节系统将永远不会在通用计算机中再次出现。
我的预期是,未来的可移植性问题将是硬件具有至少 16 位或 32 位访问权限,使得 CHAR_BIT 至少为 16。此处的仔细设计可能有助于处理任何意外的 9 位字节。
对/的问题。读者:有没有人知道今天生产中使用 9 位字节或补码算法的通用 CPU?我可以看到嵌入式控制器可能存在的位置,但仅此而已。
长答案
早在 1990 年代,计算机和 Unicode 的全球化让我期望 UTF-16 或更大,以推动每字符位数的扩展:C 中的 CHAR_BIT。但由于遗留的寿命比一切都长,我也期望 8 位字节至少只要计算机使用二进制文件,它就仍然是一个行业标准。
BYTE_BIT:每字节位数(流行,但不是我所知道的标准)
BYTE_CHAR:每字符字节数
C 标准没有解决消耗多个字节的字符。它允许它,但没有解决它。
3.6 字节: ( C11 标准 ISO/IEC 9899:201x最终草案)
数据存储的可寻址单元,大到足以容纳执行环境的基本字符集的任何成员。
注 1:可以唯一地表示对象的每个单独字节的地址。
注 2:一个字节由一个连续的比特序列组成,其数量由实现定义。最低有效位称为低位;最高有效位称为高位。
在 C 标准定义如何处理大于 1 的 BYTE_CHAR 值之前,我不是在谈论“宽字符”,这是可移植代码必须解决的主要因素,而不是更大的字节。CHAR_BIT 为 16 或 32 的现有环境是要研究的。ARM 处理器就是一个例子。我看到了两种读取外部字节流的基本模式,开发人员需要从中选择:
- 解压:将一个 BYTE_BIT 字符转换为本地字符。当心符号扩展。
- 打包:将 BYTE_CHAR 字节读入本地字符。
便携式程序可能需要一个 API 层来解决字节问题。为了即时创造和想法,我保留将来攻击的权利:
#define BYTE_BIT 8 // 每字节位数
#define BYTE_CHAR (CHAR_BIT/BYTE_BIT) //bytes-per-char
size_t byread(void *ptr,
size_t size, // BYTE_BIT 字节数
int packing, // 每个字符要读取的字节数
//(符号扩展为负数)
文件*流);
size_t bywrite(void *ptr,
size_t 大小,
内包装,
文件*流);
size
要传输的 BYTE_BIT 字节数。
packing
每个char字符传输的字节数。虽然通常为 1 或 BYTE_CHAR,但它可以指示外部系统的 BYTE_CHAR,它可以小于或大于当前系统。
- 永远不要忘记字节顺序冲突。
避免 9 位系统:
我之前为 9 位环境编写程序的经验让我相信我们不会再看到这种情况,除非你碰巧需要一个程序在某个地方的真正旧的遗留系统上运行。可能在32/64 位系统上的9 位 VM中。自 2000 年以来,我有时会快速搜索但没有看到对旧 9 位系统当前后代的引用。
在我看来,任何非常出乎意料的未来通用 9 位计算机都可能具有 8 位模式或 8 位 VM(@jstine)来运行程序。唯一的例外是专门构建的嵌入式处理器,通用代码无论如何都不太可能在其上运行。
在过去,一台 9 位机器是 PDP/15。十年与这种野兽的克隆搏斗让我从没想过会再次出现 9 位系统。我对为什么遵循的首选:
- 额外的数据位来自于抢夺核心内存中的奇偶校验位。旧的 8 位内核带有一个隐藏的奇偶校验位。每个制造商都这样做了。一旦内核变得足够可靠,一些系统设计人员会迅速将现有的奇偶校验转换为数据位,以便在非 MMU 机器较弱的时候获得更多的数字能力和内存地址。现在的内存技术没有这么奇偶校验位,机器没那么弱,64位内存这么大。所有这些都应该使设计更改的成本效益低于当时的更改。
- 在 8 位和 9 位架构之间传输数据,包括现成的本地 I/O 设备,而不仅仅是其他系统,一直是一个痛苦的过程。同一系统上的不同控制器使用了不兼容的技术:
- 使用 18 位字的低 16 位。
- 使用 9 位字节的低 8 位,其中额外的高位可能设置为从奇偶校验敏感设备读取的字节的奇偶校验。
- 将三个 8 位字节的低 6 位组合成 18 位二进制字。
一些控制器允许在运行时选择 18 位和 16 位数据传输。您的程序会发现什么样的未来硬件和支持系统调用,只是无法提前预测。
- 连接到 8 位互联网本身就足以扼杀任何人的 9 位梦想。当时他们侥幸逃脱,因为当时机器之间的互联程度较低。
- 在字节寻址存储中拥有 2 位的偶数倍数以外的东西会带来各种麻烦。示例:如果您想要一个 8 位字节中包含数千位的数组,您可以
unsigned char bits[1024] = { 0 }; bits[n>>3] |= 1 << (n&7);
. 要完全打包 9 位,您必须进行实际除法,这会带来可怕的性能损失。这也适用于每字字节数。
- 任何没有在 9 位字节硬件上实际测试过的代码都可能在第一次实际冒险进入意想不到的 9 位字节领域时失败,除非代码非常简单,以至于将来为 9 位重构它只是一个小问题. 之前的 byread()/bywrite() 在这里可能会有所帮助,但它可能需要额外的 CHAR_BIT 模式设置来设置传输模式,返回当前控制器如何排列请求的字节。
为了完整起见,任何想要为教育体验担心 9 位字节的人可能还需要担心自己的补码系统会回来;其他似乎已经死的当之无愧的死亡(两个零:+0和-0,是持续噩梦的根源……相信我)。那时 9 位系统似乎经常与补码运算配对。