用于表示 ANSI (C89/90) C 中的字节的类型?
Posted
技术标签:
【中文标题】用于表示 ANSI (C89/90) C 中的字节的类型?【英文标题】:Type to use to represent a byte in ANSI (C89/90) C? 【发布时间】:2010-10-01 01:11:45 【问题描述】:在 ANSI (C89/90) C 中是否有标准投诉方法来表示一个字节?我知道,大多数情况下,一个字符恰好是一个字节,但我的理解是,不能保证一定是这样。还有,C99标准里有stdint.h,但是C99之前用的是什么?
我对 8 位和一个“字节”(sizeof(x) == 1)都很感兴趣。
【问题讨论】:
确保区分字节和八位字节。 sizeof(char) = 1 总是,这意味着一个 char 总是一个字节。但是,一个字节并不总是一个八位字节(DEC Alpha 字节为 10 位,IIRC...八位字节被定义为 8 位)。 【参考方案1】:在 C99 之前?平台相关代码。
但是你为什么在乎呢?只需使用 stdint.h。
在我使用的每个 C 实现中(从旧的 UNIX 到硬件工程师编写的嵌入式编译器再到大型供应商编译器)char
一直是 8 位的。
【讨论】:
那么您的建议是使用 uint8_t 还是使用 unsigned char? 有趣的是,我上学的时候,一个字符是 6 位的。小写成本为 12 位!我认为您不会错过我们曾经使用过的 36 位、60 位和其他有趣的机器。【参考方案2】:你可以在 boost.js 中找到非常可靠的宏和 typedef。
【讨论】:
好吧,你可以从那里复制/粘贴你需要的东西。如果您只需要一定长度的可靠整数类型,则没有什么特别之处。【参考方案3】:您总是可以用无符号字符表示一个字节(如果您指的是 8 位)。它的大小始终至少为 8 位,所有位都构成该值,因此 8 位值将始终适合它。
如果你想要 8 位,我也认为你必须使用平台相关的方式。 POSIX 系统似乎是required 来支持int8_t。这意味着在 POSIX 系统上,char(因此是一个字节)总是 8 位。
【讨论】:
POSIX 对 stdint.h 后期 C99 的支持。 啊,是的。看起来像是从 2001 年开始的。但我认为即使他没有提供 c99 编译器 - 如果他在 posix 机器上,他可以利用 stdint.h 的要求。如果他在 ms windows 上,我所有的赌注都没有了 :) 也许他可以从 boost 的 cstdint.hpp 中抓取东西并 c'ify 他们? 我的意思是一个字节,不一定是 8 位,但是谢谢。顺便说一句,规范是否说它必须至少为 8 位,还是恰好是这种情况? 是的,c 标准记录 limits.h 要求 UCHAR_MAX 至少为 255,没有填充位并使用纯二进制系统。 char 必须具有与 unsigned char 或 signed char 相同的范围和表示形式,但仍必须是不同的类型。【参考方案4】:char
始终是 byte ,但并不总是 octet。字节是内存的最小可寻址单元(在大多数定义中),八位字节是 8 位内存单元。
也就是说,对于所有实现,sizeof(char)
始终为 1,但 limits.h
中的 CHAR_BIT
宏定义了平台的字节大小,并不总是 8 位。有 16 位和 32 位字节的平台,因此char
会占用更多位,但它仍然是一个字节。由于char
所需的范围至少为 -127 到 127(或 0 到 255),因此在所有平台上它都至少为 8 位。
ISO/IEC 9899:TC3
6.5.3.4 sizeof 运算符
... sizeof 运算符产生其操作数的大小(以字节为单位),它可以是表达式或带括号的类型名称。 [...] 当应用于类型为
char
、unsigned char
或signed char
(或其限定版本)的操作数时,结果为1。 [...]
强调我的。
【讨论】:
char 所需的范围实际上是 -127 到 127(不要忘记某些架构曾经使用有符号幅度或补码整数表示)或 0 到 255,具体取决于 char 是否有符号或未签名。 8 位二进制补码支持 -128 到 127,而不是 -127 到 128。 @Chris: byte = 最小的可寻址内存单元。我不确定你的问题是什么意思。小于 8 位字节意味着平台不能与 C 兼容。 没有意识到 C 需要 >=8 位字节(实际上,标准规定一个字节必须包含一个 char,一个 char 必须是 8 位)。我们已经到达了 C 语言可移植性的前沿…… @theduke,主要是DSP,例如:leo.sprossenwanne.at/dsp/Entwicklungsprogramme/Entpack/CC56/DSP/… 只要 C 实现提供的 逻辑字节 至少为 8 位,就 C 一致性而言,小于 8 位的物理硬件字节是没有问题的。这意味着具有 7 位硬件字节的机器可以为char
提供 14 位逻辑字节并且是一致的,但是所有较大的类型都必须占用整数(并且对齐)数量的此类逻辑字节(即,您可以没有由 3 个硬件字节组成的 21 位整数,除非您包含额外的 7 位填充(第二个 char
的其余部分)。【参考方案5】:
在 ANSI C89/ISO C90 中 sizeof(char) == 1。但是,1 字节并不总是 8 位。如果您想计算 1 个字节中的位数(并且您无权访问 limits.h),我建议如下:
unsigned int bitnum(void)
unsigned char c = ~0u; /* Thank you Jonathan. */
unsigned int v;
for(v = 0u; c; ++v)
c &= c - 1u;
return(v);
这里我们使用 Kernighan 的方法来统计 c 中设置的位数。为了更好地理解上面的代码(或看到其他类似的代码),我推荐你“Bit Twiddling Hacks”。
【讨论】:
使用 ~0 比使用 -1 更好;在一个补码或符号幅度机器上,-1 可能不是全位设置。 ~0 保证所有位都设置。 @Jonathan:这是有道理的。感谢您的建议。我现在正在编辑帖子。 (很抱歉我多次编辑此评论!) 它在数学上定义:-N 是 (2^CHAR_BIT - (N mod (2^CHAR_BIT))) 这意味着,-1 始终是最高的无符号字符,所有位都为 1。在符号表示中,如果您有二进制补码,则转换是概念性的:位模式不会改变: @R:这怎么可能?一个补码意味着,对于 16 位整数,-1 是 %11111111-11111110,因为要生成负数,只需翻转位 (see here)。仅对于二进制补码 -1 将是 %11111111-11111111,即 0x7FFFF + 1(这是许多 CPU 设置溢出标志的时候)。 @AndreasSpindler:见 JohannesSchaub-litb 的评论:从有符号到无符号的转换不仅仅是位模式的重新解释,从概念上讲,你添加 Uxxx_MAX 直到你在范围内。【参考方案6】:我注意到有些回答已将单词 byte 重新定义为 8 位以外的意思。 一个字节是 8 位,但是在某些 c 实现中 char 是 16 位(2 字节)或 8 位(1 字节)。将字节称为“最小可寻址内存单元”或一些此类垃圾的人已经失去了对字节(8位)含义的理解。 C 的一些实现有 16 位字符(2 个字节)和一些有 8 位字符(1 个字节),并且没有称为“字节”的标准类型,这是由于懒惰。
所以,我们应该使用 int_8
【讨论】:
语言标准已将“字节”一词的其含义定义为最小的可寻址单元。这不一定是 8 位。在某些系统上它可能更大。这些系统也不太可能有 int_8(或 int8_t)。 并非不可能。int8_t
是必需的(如果存在),没有填充位(和二进制补码表示),所以它存在的唯一方法是 char
正好是 8 位。
字节传统上 not 表示 8 位。例如:FTP 使用单独的控制和数据连接的主要原因是能够为数据连接选择合适的字节大小,例如:对于 36 位计算机。请注意,RFC 使用术语 octet(并避免使用不明确的术语字节)来表示 8 位数据单元。以上是关于用于表示 ANSI (C89/90) C 中的字节的类型?的主要内容,如果未能解决你的问题,请参考以下文章