无符号减法在包裹时如何工作?

时间:2013-04-25 19:42:04

标签: c

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

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

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

任何人都可以解释发生了什么以及为什么上述工作?

3 个答案:

答案 0 :(得分: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时,宏也将返回最大值<&lt; min使用上述算法,因此有用。

答案 1 :(得分:0)

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

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

现在我们说我们做了b0010 - b0100。最终以b1110结束。未签名,这是14,签名为-6。

答案 2 :(得分:0)

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

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