C语言 翻转字节,做算术并再次翻转它们



我有一个与编程/数学相关的问题,关于在大端序和小端序之间进行转换以及进行算术。

假设我们在小端模式下有两个整数:

int a = 5;
int b = 6;
//a+b = 11

让我们翻转字节并再次添加它们:

int a = 1280;
int b = 1536;
//a+b = 2816

现在,如果我们翻转2816的字节顺序,我们会得到11.所以基本上我们可以在小端序和大端序之间进行算术计算,一旦转换,它们代表相同的数字?

这在计算机科学界有理论/名称吗?

如果添加涉及携带,则不起作用,因为携带是从右向左传播的。交换数字并不意味着携带开关方向,因此溢出到下一个字节的任何字节都会有所不同。

让我们看一个十六进制的例子,假装字节序意味着每个 4 位半字节被交换:

int a = 0x68;
int b = 0x0B;
//a+b:  0x73
int a = 0x86;
int b = 0xB0;
//a+b: 0x136

816+ B 16 是 1316该 1 被携带并添加到第一个和中的 6。但是在第二个总和中,它不是向右携带并添加到 6 中,而是向左移动并溢出到第三个十六进制数字中。

首先,应该注意的是,你假设C 中的int有 16 位错误的。在大多数现代系统中,int是 32 位类型,因此如果我们反转(不是翻转,这通常意味着取补码)5 的字节,我们将得到 83886080 (0x05000000),而不是 1280 (0x0500)

  • C 的大小是"整数"是 2 字节还是 4 字节?
  • C++标准规定了 int、long 类型的大小是什么?

另请注意,您应该用十六进制书写以使其更容易理解,因为计算机不能以十进制工作:

int16_t a = 0x0005;
int16_t b = 0x0006;
// a+b = 0x000B
int16_t a = 0x0500; // 1280
int16_t b = 0x0600; // 1536
//a+b = 0x0B00

好吧,正如其他人所说,ntohl(htonl(5) + htonl(6))恰好与 5 + 6 相同,只是因为你的数字很小,它们的反向总和不会溢出。选择更大的数字,您将立即看到差异


但是,对于值存储在 2 个较小部分中的系统,该属性确实在 1 的补码中成立,如下所示

在补码中,通过将执行传播回进位来进行算术。这使得一个人的补码算术字节序独立,如果一个人只有一个内部的"进位中断"(即存储的值被分解成两个单独的块),因为"循环进位">

假设我们有 xxyy 和 zztt,那么 xxyy + zztt 是这样完成

carry
xx        yy
+ zz <───── tt
──────────────
carry aa        bb
│             ↑
└─────────────┘

当我们反转块时,yyxx + ttzz 以相同的方式传输。因为 xx、yy、zz、tt 是任意长度的位块,所以它适用于 PDP 的混合字节序,或者当您将 32 位数字存储在两个 16 位部分中时,将 64 位数字存储在两个 32 位部分中......

例如:

  • 0x7896 + 0x6987 = 0xE21D
    • 0x9678 + 0x8769 = 0x11DE1 → 0x1DE1 + 1 = 0x1DE2
  • 0x2345 + 0x9ABC = 0xBE01
    • 0x4523 + 0xBC9A = 0x101BD → 0x01BD + 1 = 0x01BE
  • 0xABCD + 0xBCDE = 0x168AB → 0x68AB + 1 = 0x68AC
    • 0xCDAB + 0xDEBC = 0x1AC67 → 0xAC67 + 1 = 0xAC68

或者约翰·库格尔曼上面的例子:0x68 + 0x0B = 0x73; 0x86 + 0xB0 = 0x136 → 0x36 + 1 = 0x37

末端进位是选择 1 补码作为 TCP 校验和的原因之一,因为您可以轻松计算更高精度的总和。 16 位 CPU 可以像普通一样在 16 位单元中工作,但 32 位和 64 位 CPU 可以并行添加 32 位和 64 位块,而不必担心在 SIMD 不可用时(如 SWAR 技术)的进位

这似乎只是因为您碰巧选择了足够小的数字,以便它们及其总和适合一个字节。只要您的数字中的所有内容都保持在各自的字节内,您显然可以随心所欲地洗牌和取消洗牌,这不会有什么不同。如果你选择更大的数字,例如 1234 和 4321,你会注意到它不再起作用。事实上,您很可能最终会调用未定义的行为,因为您的int会溢出......

除此之外,您几乎肯定会想阅读以下内容:https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html

最新更新