C语言 字节序可以指字节中的位顺序吗?

bf1o4zei  于 2023-06-05  发布在  其他
关注(0)|答案(6)|浏览(362)

我在阅读“学习核心音频:A Hands-On Guide to Audio Programming for Mac and iOS”作者Chris Adamson曾这样描述big-endian:
字节或字的高位在数字上比低位更有效。
然而,到目前为止,我认为大小端的问题只适用于字节顺序,而不是位顺序。一个字节具有相同的位顺序(从左到右),无论我们谈论的是little endian还是big endian系统。我说错了吗?作者错了吗?还是我误解了他的观点?

vx6bjr1n

vx6bjr1n1#

由于您通常无法单独寻址一个字节中的位,因此通常没有“位字节序”的概念。

ncgqoxb0

ncgqoxb02#

这不是对所述问题的回答----其他人已经很好地回答了这个问题----而是解释一些术语的脚注,希望它能澄清相关的概念。特别是,这根本不是c所特有的。

*字节序和字节顺序

当一个大于byte的值被存储或序列化为多个字节时,组件字节存储顺序的选择称为 byte orderendianendianness
从历史上看,使用的字节顺序有三种:* “big-endian”“little-endian”* 和 “PDP-endian”“middle-endian”

  • Big-endian* 和 little-endian 字节顺序名称是从它们对字节的排序方式派生出来的:big-endian将最高有效字节(对逻辑值影响最大的字节)放在第一位,后续字节按有效性降序排列;而little-endian将最低有效字节放在第一位,连续的字节按有效性的递增顺序。

注意,对于整数类型和floating-point types,字节顺序可能不同;它们甚至可以在单独的硬件单元中实现。不过,在大多数硬件上,它们确实具有相同的字节顺序。

*位序

位顺序与字节序非常相似,不同之处在于它涉及单个位而不是字节。这两个概念是相关的,但并不相同。
位顺序仅在位被串行化时才有意义,例如经由串行或SPI或I2C总线;一个接一个。
当位在并行使用的更大组 * 中被引用时,作为一个单元 *,如字节或字,没有顺序:只有 * 标记 * 和 * 重要性 *。(这是因为它们是作为一个组并行访问和操作的,而不是一个接一个地串行访问和操作的,所以没有特定的顺序。他们作为一个群体的解释产生了不同的意义,我们人类可以标记或编号,以便于参考。

*位重要性

当一组位被视为二进制值时,存在 * 最低有效位 * 和 * 最高有效位 。这些名称源自这样一个事实,即如果更改最低有效位,位组的值更改的量将尽可能小;如果更改最高有效位,则位组的值将以最大可能的量更改(单个位更改)。
假设您有一组五位,例如 abcde,它们构成一个五位无符号整数值。如果 a 是最高有效位,e 是最低有效位,其他三个按有效位递减的顺序排列,则无符号整数值为
value = a ·24 + b ·23 + c ·22 + d ·21 + e ·20

value = 16 a + 8 b + 4 c + 2 d + e
换句话说,
位有效性 * 是从一组位的数学(或逻辑)解释中得出的,并且与位在某些总线上可能被串行化的顺序完全分离,并且也与任何人为分配的标签或数字完全分离。
这对于逻辑上构造数值的所有位组都是如此,甚至对于floating-point数字也是如此。

*位标签或位编号

例如,为了便于在文档中引用,标记各个位通常是有用的。这基本上是任意的;事实上,我在上面的例子中使用了字母 af。通常情况下,数字比字母更容易-用单个字母标记超过27位并不容易。
有两种用数字标记位的方法。
目前最常见的方法是根据位的有效性来标记位,其中位0表示最低有效位。这是有用的,因为位 i 然后具有逻辑值2x 1 m11n1x。
在某些体系结构的文档中,如IBM的POWER文档,最高有效位按有效性降序标记为0。在这种情况下,位的逻辑值取决于该单元中的位数。如果单元具有N位,则位i具有2x 1 m14n1x-i-1的逻辑值。
虽然这种排序可能感觉很奇怪,但这些架构都是big-endian的,对于人类来说,记住/假设这些系统上 * 最重要的优先级 * 可能是有用的。
然而,请记住,这是一个完全任意的决定,在这两种情况下,文档都可以使用 other 位标记方案编写,而不会对系统的实际性能产生任何影响。这就像选择从左到右写,还是从右到左写(或者从上到下写):内容不受影响,* 只要您知道并理解约定 *。

虽然字节顺序和位标记之间存在一些相关性,但上述所有四个概念都是独立的。
字节顺序和位标记之间存在相关性-在这个意义上,许多大端硬件的文档使用位标记,其中最高有效位是位0-但这只是因为人类做出的选择。

c中,C编译器将位字段打包到结构体中的顺序因编译器和体系结构而异。C标准根本没有指定它。因此,将二进制文件读入带位字段的结构类型通常是个坏主意。(即使它在某些特定的机器和编译器上工作,也不能保证它在其他机器上也能工作;但通常并不如此。因此,它肯定会降低代码的可移植性。)相反,读取一个缓冲区和unsigned char数组,并使用helper accessor 函数从数组中提取位字段,使用移位(<<>>),二进制或(|)和掩码(二进制和,&)。

zaq34kh6

zaq34kh63#

存在“位顺序”的唯一意义是位被分配给位域的顺序。例如,在:

union {
    struct {
        unsigned char a:4;
        unsigned char b:4;
    } bf;
    unsigned char c;
};

取决于实现,bf.a的表示可以占用c的高四位,或者c的低四位。位域成员的顺序是否与字节顺序匹配是实现定义的。

2j4z5cfb

2j4z5cfb4#

一个字节按位顺序的“字节序”并不是一个真正的问题,除非您使用的是一个允许您单独寻址位的特殊系统。在决定如何通过线路传输数据时,这可能是一个问题,但这个决定通常是在硬件级别做出的。

音频

就与***音频流***的相关性而言,它可能非常重要。负责将数字音频流转换成模拟音频信号的硬件可以期望流中的位处于特定顺序。如果他们错了,声音可能会完全崩溃。也许你的书的作者详细阐述了这一点?无论如何,正如我前面提到的,这通常是在硬件级别决定的,在用户甚至内核级别编程时并不是一个真正的问题。通常,行业标准将定义两个硬件将如何彼此传输数据。只要您的所有硬件都同意位字节序,那么一切都很好。
在Wikipedia进一步阅读。

wz3gfoph

wz3gfoph5#

字节中的位的顺序没有意义,字节中的位是不可寻址的,因此您无法定义这些位的顺序以将其用作endianness定义的引用。与位不同,字节是可寻址的,因此有一个地址顺序,我们可以使用它作为参考来定义小端或大端的含义。
您可能会有这样的印象,即Left shift <<Right Shift >>按位运算符间接地暗示了字节内部有一个定义的位顺序,但事实并非如此。这两个术语基于抽象字节表示,其中最低位位于右侧,向左移动时位的值变高,但根据定义,Left shift与乘以2具有相同的效果,Right shift与除以2具有相同的效果(对于无符号整数)。

hi3rlvi2

hi3rlvi26#

位5是索引5处的位,而不是&byte+5bits的地址处的位。您的计算机将根据索引位而不是物理位来理解所有位操作。
当然,当你必须保证一定的位序列时,“位字节序”仍然很重要,例如。在网络协议或外围设备(例如SPI总线)上,但在这种情况下,您的库可能会说“数据总是MSB优先发送”,这意味着每个字节都以最高有效位优先发送,这就解决了这个问题。

相关问题