6

这是 lwIP 源代码中的一个宏:

#define TCP_SEQ_LT(a,b)     ((int32_t)((uint32_t)(a) - (uint32_t)(b)) < 0)

它用于检查 TCP 序列号是否小于另一个,考虑到序列号何时回绕。它利用了算术环绕的事实,但我无法理解在这种特殊情况下它是如何工作的。

谁能解释发生了什么以及为什么上述工作?

4

3 回答 3

3

举一个简单的 4 位整数示例,其中 a = 5 和 b = 6。每个整数的二进制表示形式为

a = 0101
b = 0110

现在,当我们减去这些(或取 b 的补码,与 a 相加,然后加 1)时,我们得到以下结果

0101
1001
+  1
-----
1111

1111 等于 15(无符号)或 -1(有符号,再次使用二进制补码翻译)。通过将这两个数字转换为无符号数,我们确保如果 b > a,则两者之间的差将是一个很大的无符号数,并且设置了它的最高位。当把这个大的无符号数转换成它的有符号数时,由于设置了 MSB,我们总是会得到一个负数。

正如 nos 所指出的,当序列号从最大无符号值回绕回最小值时,宏还将使用上述算术返回最大值 < min,因此它很有用。

于 2013-04-25T19:54:38.640 回答
0

在环绕时,a 将比 b 大得多。如果我们减去它们,结果也会非常大,即设置了它的高位。如果我们然后将结果视为有符号值,则较大的差异将变为负数,小于 0。

如果您有 2 个相隔 2G 的序列号,它将不起作用,但这不会发生。

于 2013-04-25T19:51:47.163 回答
0

因为它在与零比较之前首先被转换为有符号整数。请记住,从左到右读取的第一位确定有符号数的符号,但用于将 unsigned int 的范围增加一个额外的位。

示例:假设您有一个 4 位无符号数。这意味着 1001 是 17。但作为有符号整数,这将是 -1。

现在假设我们做了 b0010 - b0100。这以 b1110 结束。无符号是 14,有符号的是 -6。

于 2013-04-25T19:47:58.357 回答