什么平台有8位字符以外的东西?
SO上的某个人偶尔指出char
(又称“字节”)不一定是8位 。
似乎8位char
几乎是通用的。 我认为对于主stream平台来说,有必要有一个8位char
来确保它在市场上的可行性。
现在和历史上,哪个平台使用的char
不是8位,为什么它们与“正常”8位不同呢?
在编写代码时,考虑跨平台的支持(例如,对于通用库),值得给予非8位char
平台值得考虑什么?
在过去,我遇到了一些char
为16位的ADI公司的DSP。 DSP是我想的一个小众体系结构。 (再次,当时手工编译的汇编程序很容易打败可用的C编译器可以做的事情,所以我在那个平台上并没有真正的C经验。)
德州仪器C54x DSP上的char
也是16位的,例如OMAP2。 还有其他的DSP 16和32位char
。 我想我甚至听说过一个24位的DSP,但我不记得是什么,所以也许我想到了它。
另一个考虑是POSIX强制CHAR_BIT == 8
。 所以如果你使用的是POSIX,你可以假设它。 如果以后有人需要将你的代码移植到POSIX的接近实现中,那么恰好有你使用的函数,但是不同大小的char
,这是他们运气不好。
但总的来说,我认为解决这个问题几乎总是比较容易,而不是思考问题。 只需键入CHAR_BIT
。 如果你想要一个确切的8位types,使用int8_t
。 你的代码将无法在不提供的代码上编译,而不是默默地使用你没有想到的大小。 至less,如果我遇到了一个我有充分理由承担的情况,那么我就会断言。
在编写代码时,考虑跨平台的支持(例如,对于通用库),值得给予非8位字符的平台值得考虑什么?
与其说是规则所扮演的angular色,不如说是“值得考虑”。 例如在C ++中,标准说所有的字节都会有“至less”8位。 如果你的代码假定字节只有8位,那么你违反了标准。
这看起来可能很愚蠢 – “ 当然,所有的字节都有8位!”,我听到你在说。 但是很多非常聪明的人都依赖于不能保证的假设,然后一切都破裂了。 历史充满了这样的例子。
例如,大多数90年代早期的开发人员认为,一个特定的无操作CPU时钟延迟花费固定数量的周期将花费固定的时钟时间,因为大多数消费者CPU的功耗大致相当。 不幸的是,电脑变得非常快。 这就产生了带有“Turbo”button的盒子的崛起 – 具有讽刺意味的是,它的目的是减慢计算机的速度,使得使用时间延迟技术的游戏可以以合理的速度播放。
一位评论者询问标准中的字符必须至less有8位。 在5.2.4.2.1节。 本节定义了CHAR_BIT
(最小可寻址实体中的位数),默认值为8.它还表示:
它们的实现定义的值应该等于或大于所示的数值(绝对值),具有相同的符号。
所以任何等于8或更高的数字都适合用CHAR_BIT
实现来替代。
具有36位体系结构的机器具有9位字节。 根据维基百科, 具有36位体系结构的机器包括:
- 数字设备公司PDP-6/10
- IBM 701/704/709/7090/7094
- UNIVAC 1103 / 1103A / 1105/1100/2200,
其中一些我知道:
- DEC PDP-10:可变的,但最常见的是7位字符,每36位字符打包5个字符,或者9位字符,每个字符4个
- 控制数据主机(CDC-6400,6500,6600,7600,Cyber 170,Cyber 176等)6位字符,每60位字符打包10个字符。
- Unisys主机:9位/字节
- Windows CE:根本不支持`char`types – 需要16位wchar_t来代替
没有完全可移植的代码这样的事情。 🙂
是的,可能有不同的字节/字符大小。 是的,对于具有极不寻常的CHAR_BIT
和UCHAR_MAX
值的平台,可能会有C / C ++实现。 是的,有时可以编写不依赖字符大小的代码。
但是,几乎任何实际的代码都不是独立的。 例如,您可能正在编写一个向networking发送二进制消息的代码(协议不重要)。 您可以定义包含必要字段的结构。 比你必须序列化它。 只是将结构二进制复制到输出缓冲区中是不可移植的:通常,您不知道平台的字节顺序,也不知道结构成员alignment方式,所以结构只是保存数据,而没有描述数据应该被序列化的方式。
好。 您可以执行字节顺序转换,并使用memcpy
将结构成员(例如uint32_t
或类似的)移动到缓冲区中。 为什么使用memcpy
? 因为当目标地址未正确alignment时,有很多平台无法写入32位(16位,64位 – 没有区别)。
所以,你已经做了很多工作来实现可移植性。
现在是最后一个问题。 我们有一个缓冲区。 来自它的数据被发送到TCP / IPnetworking。 这样的networking假定8位字节。 问题是:什么types的缓冲区应该是? 如果你的字符是9位? 如果他们是16位? 24? 也许每个字符对应一个8位字节发送到networking,只有8位被使用? 或者也许多个networking字节被打包成24/16/9-bit字符? 这是一个问题,很难相信有一个适合所有情况的答案。 很多东西都依赖于目标平台的套接字实现。
所以,我在说什么。 通常代码在一定程度上可以相对容易地移植 。 如果您期望在不同平台上使用代码,那么这么做非常重要。 然而, 提高超出这个度量的可移植性是一件需要付出很多努力的东西,并且通常几乎没有 ,因为真正的代码几乎总是依赖于其他代码(上面的示例中的套接字实现)。 我相信,在8位以外的字节平台上工作的代码能力的90%几乎是无用的,因为它使用了绑定到8位的环境。 只要检查字节大小并执行编译时间断言。 你几乎肯定会重写很多非常不寻常的平台。
但是,如果你的代码是高度“独立”的 – 为什么不呢? 你可以写一个允许不同字节大小的方法。
看来,你仍然可以从仓库中购买IM6100 (即芯片上的PDP-8)。 这是一个12位的架构。
许多DSP芯片都有16位或32位char
。 例如,TI经常制造这样的芯片。
例如,C和C ++编程语言将字节定义为“足以容纳执行环境的基本字符集的任何成员的数据的可寻址单元”(C标准的第3.6节)。 由于C char整数数据types必须至less包含8位(第5.2.4.2.1节),所以C中的一个字节至less能够保存256个不同的值。 C和C ++的各种实现将字节定义为8,9,16,32或36位
引自http://en.wikipedia.org/wiki/Byte#History
不知道其他语言。
http://en.wikipedia.org/wiki/IBM_7030_Stretch#Data_Formats
定义该机器上的一个字节为可变长度
首先,Unicode字符长度超过8位。 正如前面提到的那样,C规范定义了数据types的最小尺寸。 如果你想查询你的数据types,并确切地发现你的configuration和体系结构的大小,请使用sizeof
和limits.h
的值。
出于这个原因,当我需要一个特定位长度的数据types时,我试图坚持像uint16_t
这样的数据types。
编辑:对不起,我最初误读你的问题。
C规范说, char
对象“足够大,可以存储任何执行字符集的成员”。 limits.h
列出了8位的最小大小,但是定义保留了char
的最大大小。
因此,一个char
至less与你的架构的执行集中的最大字符一样长(通常四舍五入到最接近的8位边界)。 如果你的架构有较长的操作码,你的char
大小可能会更长。
历史上,x86平台的操作码是一个字节长,所以char
最初是一个8位值。 目前的x86平台支持超过一个字节的操作码,但是char
长度保持在8位,因为这是程序员(和大量现有的x86代码)的条件。
在考虑多平台支持时,请利用stdint.h
定义的types。 如果使用(例如)uint16_t,则可以确定此值在任何体系结构上都是无符号的16位值,无论该16位值是对应于char
, short
, int
还是其他值。 编写你的编译器/标准库的人已经完成了大部分的努力工作。
如果您需要知道char
的确切大小,因为您正在进行一些需要的低级别硬件操作,我通常使用足够大的数据types来在所有支持的平台上保存char
(通常16位就足够了)当我需要确切的机器表示时,通过convert_to_machine_char
例程运行该值。 这样,特定于平台的代码被限制在接口函数中,大部分时间我都可以使用正常的uint16_t
。
DEC PDP-8家族有一个12位的字,尽pipe你通常使用8位ASCII码输出(主要是电传打字)。 但是,也有一个6位字符代码,允许您在一个12位字中编码2个字符。
什么样的考虑是值得给非8位字符的平台?
幻数出现,例如,当转移;
大多数这些可以很简单地通过使用CHAR_BIT和例如UCHAR_MAX而不是8和255(或类似的)来处理。
希望你的实现定义了那些:)
这些是“常见”问题…..
另一个间接的问题是说你有:
struct xyz { uchar baz; uchar blah; uchar buzz; }
这可能“仅”在一个平台上采用(最好的情况下)24比特,但是可能在其他地方采用例如72比特…..
如果每个uchar保存“比特标志”,并且每个uchar只有2个“重要”比特或标志,而且你只把它们组织成3个“清晰”的uchar,那么它可能相对“更浪费”一个24位uchars平台…..
没有任何位域不能解决,但他们有其他的事情要注意….
在这种情况下,只有一个枚举可能是一种方法来获得您实际需要的“最小”大小的整数。
也许不是一个真实的例子,但像这样的东西“位”时,移植/播放一些代码…..
只是事实上,如果uchar是“正常”预期的三倍,那么100个这样的结构可能会在一些平台上浪费大量内存…..在“正常”情况下,这不是什么大问题…. 。
所以事情仍然可能被“破坏”,或者在这种情况下“非常快速地浪费大量的内存”,这是由于假定uchar在一个平台上相对于可用RAM而言“不是非常浪费”,而不是在另一个平台上。 ..
这个问题可能会更加突出,例如对于整数,或者其他types,比如你有一些需要15位的结构,所以你把它放在一个int中,但是在其他一些平台上int是48位或者任何其他的。 。
“通常”,你可能会把它分成2个,但是例如24位的uchar,你只需要一个……
所以枚举可能是一个更好的“通用”解决scheme….
取决于你如何访问这些位虽然:)
所以,可能会有“devise上的缺陷”,即使代码可能仍然工作/运行良好,无论uchar或uint的大小如何…
有这样的事情要注意,即使你的代码中没有“魔术数字”…
希望这是有道理的:)
整数曾经是16位(pdp11等)。 去32位体系结构很难。 人们变得越来越好:几乎没有人会假设一个指针会长时间适应(你不对?)。 或文件偏移,或时间戳,或…
8位字符已经有点不合时宜了。 我们已经需要32位来保存世界上所有的字符集。