Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does unsigned subtraction work when it wraps around?

Tags:

c

This is a macro in the lwIP source code:

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

Which is used to check if a TCP sequence number is less than another, taking into account when the sequence numbers wrap around. It exploits the fact that arithmetic wraps around, but I am unable to understand how this works in this particular case.

Can anyone explain what happens and why the above works ?

like image 957
user1255770 Avatar asked Apr 25 '13 19:04

user1255770


People also ask

Can you subtract unsigned numbers?

Subtracting two unsigned values of the same size will result in an unsigned value. If the first operand is less than the second the result will be arithmetically in correct.

What is wrapping around in C?

An integer overflow or wraparound occurs when an integer value is incremented to a value that is too large to store in the associated representation. When this occurs, the value may wrap to become a very small or negative number.

What is an unsigned value?

Unsigned Integers (often called "uints") are just like integers (whole numbers) but have the property that they don't have a + or - sign associated with them. Thus they are always non-negative (zero or positive). We use uint's when we know the value we are counting will always be non-negative.

What is signed and unsigned addition?

Variables such as integers can be represent in two ways, i.e., signed and unsigned. Signed numbers use sign flag or can be distinguish between negative values and positive values. Whereas unsigned numbers stored only positive numbers but not negative numbers.


1 Answers

Take a simple 4 bit integer example where a = 5 and b = 6. The binary representation of each will be

a = 0101
b = 0110

Now when we subtract these (or take two's complement of b, sum with a, and add 1), we get the following

0101
1001
+  1
-----
1111

1111 is equal to 15 (unsigned) or -1 (signed, again translated using two's complement). By casting the two numbers to unsigned, we ensure that if b > a, the difference between the two is going to be a large unsigned number and have it's highest bit set. When translating this large unsigned number into its signed counterpart we will always get a negative number due to the set MSB.

As nos pointed out, when a sequence number wraps around from the max unsigned value back to the min, the macro will also return that the max value is < min using the above arithmetic, hence its usefulness.

like image 103
ryanbwork Avatar answered Nov 01 '22 05:11

ryanbwork