了解字节交换

Understanding Byte swapping

我正在尝试找出一种方法来为 64 位整数 (uint64_t) 创建一个小的 endian/big 字节序转换,同时我在网上找到了很多关于如何做的答案它,其中 none 解释了到底发生了什么。例如,要获取整数的第 n 个字节,我发现了这个响应:

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

即使我了解位移组件(向右移动 8n 位数字),我也看不出 & 和 0xff 的用处,以及除了 & 之外它们的含义是按位与运算符。

那么,这种逻辑如何应用于 64 位整数的 big-endian/little-endian 字节交换方法?

提前致谢。

可能最容易想到十进制数的类比:

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

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

小端意味着"write the least significant digit to the lowest address"; 大端表示 "write the most significant digit to the lowest address".

所以,关于处理字节顺序的机制: 如果您想到上面的小数示例,您将如何获得每个数字?最低有效数字通过取模 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。

等等。所以现在您可以访问 digits/bytes,您只需选择存储它们的顺序。根据以上,"big endian = most-significant at lowest address"、"little endian = least-significant at lowest address".