2013-04-25 11 views
6

To makro w kodzie źródłowym lwIP:Jak działa odejmowanie bez podpisu, gdy się zawija?

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

który służy do sprawdzenia, czy numer sekwencyjny TCP jest mniejsza niż inny, biorąc pod uwagę, gdy numery sekwencyjne owinąć wokół. Wykorzystuje fakt, że arytmetyka obejmuje, ale nie jestem w stanie zrozumieć, jak to działa w tym konkretnym przypadku.

Czy ktoś może wyjaśnić, co się dzieje i dlaczego powyższe działa?

+0

Wypracować za pomocą np. 8-bitowego numeru. –

+2

Chcę utworzyć kompilator, który konwertuje liczby spoza zakresu do 17, gdy typ docelowy jest podpisany. –

+0

@ Daniel Fischer Tak długo jak to dokumentujesz. –

Odpowiedz

3

Weźmy prosty 4 bitowy przykład całkowitą gdzie a = 5 ib = 6. binarna reprezentacja każdy będzie

a = 0101 
b = 0110 

Teraz, gdy odejmiemy te (lub wziąć dwa dopełnienia B, sumę z i dodać 1), otrzymujemy następujące

0101 
1001 
+ 1 
----- 
1111 

1111 jest równa 15 (unsigned) lub -1 (podpisany ponownie tłumaczone za pomocą dwóch dopełnienie). Przerzucając dwie liczby na niepodpisane, upewniamy się, że jeśli b> a, różnica między nimi będzie duża i będzie miała najwyższy ustawiony bit. Podczas tłumaczenia tego dużego niepodpisanego numeru na jego podpisany odpowiednik zawsze otrzymamy liczbę ujemną z powodu ustawionego MSB.

Jak zauważono, kiedy numer sekwencji zawija się od wartości maksymalnej unsigned do wartości min, makro zwróci również, że maksymalna wartość to < min z wykorzystaniem powyższej arytmetyki, stąd jej użyteczność.

+0

Tak, przepraszam, byłby to np. a = 14 i b = 1, co powinno dać, że a jest mniejsze niż b (lub podobne, dla wykazania przypadku owijania). – nos

+0

Dobra uwaga, zmodyfikuje moją odpowiedź na ten przykład. – ryanbwork

+0

Kiedy koduję to w praktyce, widzę ujemne wartości, gdy a = 0-> b, ale także po różnicy między tymi dwiema wartościami jest większa niż 127 (używając dwóch niepodpisanych znaków dla aib w moim przypadku). Byłoby to niedokładnie informować, że jeśli b = 64 i a = 192, to a jest mniejsze niż b. Byłoby to prawdą w przypadku == 192 -> 63. Czy możesz tutaj wyjaśnić więcej? @ryanbwork – ryeager

0

Ponieważ jest on pierwszy rzutowany jako liczba całkowita ze znakiem, zanim zostanie porównany do zera. Pamiętaj, że pierwszy odczyt bitów od lewej do prawej określa znak w podpisanym numerze, ale jest używany do zwiększenia zakresu unsigned int o dodatkowy bit.

Przykład: załóżmy, że masz 4-bitową liczbę bez znaku. Oznaczałoby to, że 1001 to 17. Ale jako liczba całkowita ze znakiem jest to -1.

Teraz możemy powiedzieć, że zrobiliśmy b0010 - b0100. Kończy się to b1110. Bez podpisu to 14, a podpisano to -6.

0

Na zawinięciu a będzie znacznie większy niż b. Jeśli je odejmiemy, wynik również będzie bardzo duży, tzn. Ma ustawiony bit wyższego rzędu. Jeśli następnie potraktujemy wynik jako wartość , to duża różnica zmieni się w liczbę ujemną, mniejszą niż 0.

Gdybyśmy mieli 2 numery sekwencji od siebie 2G, to by się nie udało, ale to się nie stanie .

Powiązane problemy