【问题标题】:Understanding Byte swapping了解字节交换
【发布时间】:2017-11-19 21:47:37
【问题描述】:

我正在尝试找出一种方法来为 64 位整数 (uint64_t) 创建一个小端/大端转换,虽然我在网上找到了很多关于如何做到这一点的答案,但他们都没有解释到底是什么正在进行。例如,要获取整数的第 n 个字节,我发现了这个响应:

int x = (number >> (8*n)) & 0xff;

即使我了解位移组件(向右移动 8n 位),我也看不到 & 和 0xff 的来源,除了 & 之外它们的含义是按位与运算符。

那么,这种逻辑如何应用于 64 位整数的大端/小端字节交换方法?

提前谢谢你。

【问题讨论】:

  • 字节序不涉及位交换,而仅涉及字节交换。从大字节序到小字节序,您必须反转构成数据字的整个字节,不理会位
  • & 0xff 和类似的掩码需要移动(或被移动)到相反字节序的 8 位。通常结果是ORred 和目标值。

标签: c byte endianness


【解决方案1】:

用十进制数来类比可能是最容易的:

取数字 308。它有三个数字,“3”、“0”和“8”。按照惯例,左边的数字比右边的数字更重要。但约定也可以很容易地采用另一种方式……数字可以以相反的顺序书写(例如,803)。

为什么这是相关的?考虑计算机上数字的十六进制表示:0xabcd0123。在严格的数学意义上,可以将此数字视为 4 基数 256 位。 (即,0xab、0xcd、0x01、0x23)。因此,字节序是关于这些 radix-256 数字在写入内存时的排序约定。

Little-endian 表示“将最低有效位写入最低地址”; Big-endian 的意思是“将最高有效位写入最低地址”。

所以,关于处理字节序的机制: 如果您考虑上面的十进制示例,您将如何获得每个数字?通过取模 10 的数字给出最低有效位(即 308 % 10 = 8)。第二个数字可以通过将数字除以 10,然后取模 10(即 308 / 10 = 30; 30 % 10 = 0)等等。

对于计算机上的二进制数据,该过程完全相同,只是它被视为 radix-256 而不是像十进制数字那样的 radix-10。这就是一些技巧的用武之地。

  1. 使用 2 的幂的模数进行模运算时,可以通过 AND 进行。让 m=256 作为我们的模数。因为 m = 2 的某个幂,所以 x % m 等价于 x & (m-1)。这是一个超出此答案范围的数字事实。
  2. 在进行 2 的幂除法时,可以通过右移进行。也就是说,让 m=256 成为我们的除数。因为 m = 2 的 8 次方,所以 x / m 等价于 x >> 8。

因此,特定于二进制字节序的序列化完全使用上述过程:

uint32_t val = 0xabcd0123;

(val & 0xff) 等价于 (val % 256),并产生 0x23。

((val >> 8) & 0xff) 等价于 ((val / 256) % 256),并产生 0x01。

((val >> 16) & 0xff) 等价于 (((val / 256)/256) % 256),并产生 0xcd。

等等。因此,现在您可以访问数字/字节,您只需选择存储它们的顺序。如上所述,“大端 = 最低地址最重要”,“小端 = 最低地址最不重要”。

【讨论】:

  • 不错的第一篇文章。欢迎!
猜你喜欢
  • 2019-01-31
  • 1970-01-01
  • 1970-01-01
  • 2018-06-21
  • 2017-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-08
相关资源
最近更新 更多