每隔一段时间,SO上有人指出char
(aka 'byte') isn't necessarily 8 bits。
似乎8位char
几乎是通用的。我原本认为,对于主流平台,有必要使用8位char
来确保其在市场中的可行性。
现在和历史上,哪些平台使用不是8位的char
,为什么它们与“正常”8位不同?
在编写代码并考虑跨平台支持时(例如,对于通用库而言),对于非8位char
的平台,值得考虑的是什么?
过去我遇到过一些char
为16位的ADI公司DSP。我认为DSP是一种利基架构。 (然后,当时手工编写的汇编程序很容易击败可用的C编译器可以做的事情,所以我在该平台上没有真正获得C的经验。)
答案 0 :(得分:75)
char
在德州仪器C54x DSP上也是16位,例如在OMAP2中出现。还有其他DSP有16位和32位char
。我想我甚至听说过24位DSP,但我记不起来了,所以也许我想象不到。
另一个考虑因素是POSIX要求CHAR_BIT == 8
。因此,如果你使用POSIX,你可以假设它。如果有人后来需要将你的代码移植到一个接近实现的POSIX,那恰好恰好有你使用的功能但是大小不同char
,那就是他们运气不好。
总的来说,我认为解决这个问题几乎总是比思考它更容易。只需输入CHAR_BIT
即可。如果您想要精确的8位类型,请使用int8_t
。你的代码将无法在没有提供代码的实现上编译,而不是默默地使用你没想到的大小。至少,如果我遇到一个我有充分理由认为它的情况,那么我就断言它。
答案 1 :(得分:36)
在编写代码并考虑跨平台支持时(例如,对于通用库而言),对于具有非8位字符的平台,值得考虑的是什么?
并不是因为规则所扮演的东西“值得考虑”。例如,在C ++中,标准规定所有字节都将具有“至少”8位。如果您的代码假设字节恰好是8位,则表示您违反了标准。
现在看起来很傻 - “当然所有字节都有8位!”,我听到你说。但是许多非常聪明的人依赖于不是保证的假设,然后一切都破裂了。历史充满了这样的例子。
例如,大多数90年代早期的开发人员认为,采用固定数量的周期的特定无操作CPU定时延迟将花费固定的时钟时间,因为大多数消费者CPU的功率大致相等。不幸的是,计算机变得非常快。这产生了带有“Turbo”按钮的盒子的兴起 - 具有讽刺意味的是,它的目的是减慢计算机速度,以便使用延时技术的游戏可以以合理的速度播放。
一位评论者询问标准在哪里说char必须至少有8位。它位于 5.2.4.2.1 部分。本节定义CHAR_BIT
,最小可寻址实体中的位数,默认值为8.它还说:
它们的实现定义值的大小(绝对值)应与所示值相等或更大,且符号相同。
因此,任何等于8或更高的数字都适合将实现替换为CHAR_BIT
。
答案 2 :(得分:31)
具有36位体系结构的计算机具有9位字节。根据维基百科,machines with 36-bit architectures包括:
答案 3 :(得分:18)
其中一些我知道:
答案 4 :(得分:15)
没有完全可移植的代码。 : - )
是的,可能有各种字节/字符大小。是的,对于具有非常不寻常的CHAR_BIT
和UCHAR_MAX
值的平台,可能会有C / C ++实现。是的,有时可以编写不依赖于字符大小的代码。
但是,几乎所有实际代码都不是独立的。例如。您可能正在编写将二进制消息发送到网络的代码(协议并不重要)。您可以定义包含必要字段的结构。比你必须序列化它。只是将结构二进制复制到输出缓冲区是不可移植的:通常你不知道平台的字节顺序,也不知道结构成员对齐,所以结构只保存数据,但没有描述数据的序列化方式
确定。您可以执行字节顺序转换,并使用uint32_t
将结构成员(例如memcpy
或类似物)移动到缓冲区中。为什么memcpy
?因为有很多平台在目标地址未正确对齐时无法写入32位(16位,64位 - 无差异)。
所以,你已经做了很多工作来实现可移植性。
现在是最后一个问题。我们有一个缓冲区。来自它的数据被发送到TCP / IP网络。这种网络假定为8位字节。问题是:缓冲区应该是什么类型的?如果你的字符是9位?如果他们是16位? 24?也许每个char对应一个发送到网络的8位字节,只使用8位?或者也许多个网络字节被打包成24/16/9位字符?这是一个问题,很难相信有一个适合所有情况的答案。很多事情都取决于目标平台的套接字实现。
那么,我在说什么。通常代码可以相对容易地在某种程度上移植。如果您希望在不同平台上使用代码,那么这样做非常重要。但是,提高超出该度量的可移植性需要付出很多努力并且通常很少提供,因为实际代码几乎总是依赖于其他代码(上例中的套接字实现)。我确信,大约90%的代码能够在具有8位以外字节的平台上工作几乎是无用的,因为它使用绑定到8位的环境。只需检查字节大小并执行编译时断言。你几乎肯定会为一个非同寻常的平台重写很多。
但如果您的代码高度“独立” - 为什么不呢?您可以以允许不同字节大小的方式编写它。
答案 5 :(得分:9)
看来您仍然可以buy an IM6100(即芯片上的PDP-8)从仓库中出来。这是一个12位架构。
答案 6 :(得分:9)
许多DSP芯片具有16位或32位char
。 TI经常制作此类芯片for example。
答案 7 :(得分:5)
例如,C和C ++编程语言将字节定义为“足够大的可寻址数据单元,以容纳执行环境的基本字符集的任何成员”(C标准的第3.6节)。由于C char整数数据类型必须至少包含8位(第5.2.4.2.1节),因此C中的一个字节至少能够保存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
将该机器上的字节定义为可变长度
答案 8 :(得分:4)
DEC PDP-8系列有一个12位字,尽管你通常使用8位ASCII输出(主要是在Teletype上)。但是,还有一个6位字符代码,允许您在一个12位字中编码2个字符。
答案 9 :(得分:3)
首先,Unicode字符长于8位。正如前面提到的那样,C规范按其最小大小定义数据类型。如果您想查询数据类型并准确发现它们对您的配置和体系结构的大小,请使用sizeof
和limits.h
中的值。
出于这个原因,当我需要特定位长的数据类型时,我会尝试坚持像uint16_t
这样的数据类型。
编辑抱歉,我最初误读了您的问题。
C规范指出char
对象“足够大以存储执行字符集的任何成员”。 limits.h
列出的最小大小为8位,但定义会保留char
的最大大小。
因此,a char
至少与架构执行集中的最大字符一样长(通常向上舍入到最近的8位边界)。如果您的架构具有更长的操作码,则char
大小可能会更长。
从历史上看,x86平台的操作码长度为一个字节,因此char
最初为8位值。当前的x86平台支持长度超过一个字节的操作码,但char
的长度保持在8位,因为这是程序员(以及大量现有x86代码)的条件。
在考虑多平台支持时,请利用stdint.h
中定义的类型。如果您使用(例如)uint16_t,那么您可以确定该值是任何体系结构上的无符号16位值,无论该16位值是否对应char
,short
, int
,或其他。编写编译器/标准库的人已经完成了大部分艰苦的工作。
如果你需要知道char
的确切大小,因为你正在做一些需要它的低级硬件操作,我通常会使用一个足够大的数据类型来保存char
在所有支持的平台上(通常16位就足够了),当我需要精确的机器表示时,通过convert_to_machine_char
例程运行该值。这样,特定于平台的代码仅限于接口函数,大多数时候我可以使用普通的uint16_t
。
答案 10 :(得分:3)
对于具有非8位字符的平台,值得给予什么样的考虑?
魔术数字例如出现转移时;
其中大部分都可以很简单地处理 通过使用CHAR_BIT和UCHAR_MAX而不是8和255(或类似)。
希望你的实现定义那些:)
这些是“常见”问题.....
另一个间接问题是你有:
struct xyz {
uchar baz;
uchar blah;
uchar buzz;
}
这可能“仅”在一个平台上采用(最佳情况)24位, 但可能需要,例如在其他地方72位.....
如果每个uchar都持有“位标志”,并且每个uchar只有2个“有效”位或标志 你目前正在使用,你只是为了“清晰”而将它们组织成3个uchars, 然后它可能相对“更浪费”,例如在24位uchars的平台上.....
没有任何位域无法解决,但他们还有其他需要注意的事项 对于....
在这种情况下,只需一个枚举就可以获得“最小” 您实际需要的大小整数....
也许不是一个真实的例子,但在移植/播放某些代码时,这样的东西“咬了”我......
事实上,如果一个uchar是“正常”预期的三倍大, 100个这样的结构可能会在某些平台上浪费大量内存..... “正常”这不是什么大问题.....
所以事情仍然可能“被打破”或者在这种情况下“很快就浪费了很多记忆” 假设uchar在一个平台上相对于可用RAM而言“不是非常浪费”,而不是在另一个平台上......
问题可能更突出,例如对于整数或其他类型, 例如你有一些需要15位的结构,所以你把它粘在一个int中, 但在某些其他平台上,int是48位或其他任何.....“通常”你可能将它分成2个uchars,但是使用24位uchar 你只需要一个......
所以enum可能是一个更好的“通用”解决方案......
取决于你如何访问这些位:)
所以,可能会有“设计缺陷”让他们头脑发热...... 即使代码可能仍然工作/运行正常,无论如何 uchar或uint的大小...
有这样的事情需要注意,即使在那里 在你的代码中没有“神奇的数字”......
希望这是有道理的:)
答案 11 :(得分:1)
整数曾经是16位(pdp11等)。转向32位架构很难。人们正在变得越来越好:几乎没有人认为指针会长得更长(你不对吗?)。或文件偏移量,时间戳,或......
8位字符已经有点过时了。我们已经需要32位来保存世界上所有的字符集。