了解字节交换
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。这是一些技巧的用武之地。
- 当以 2 的幂为模数进行取模时,您可以通过 AND 进行。让 m=256 作为我们的模数。因为 m = 2 的某个幂,所以 x % m 等于 x & (m-1)。这是超出此答案范围的数字事实。
- 除以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".
我正在尝试找出一种方法来为 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。这是一些技巧的用武之地。
- 当以 2 的幂为模数进行取模时,您可以通过 AND 进行。让 m=256 作为我们的模数。因为 m = 2 的某个幂,所以 x % m 等于 x & (m-1)。这是超出此答案范围的数字事实。
- 除以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".