這是LWIP的源代碼中的宏:無符號減法在繞回時如何工作?
#define TCP_SEQ_LT(a,b) ((int32_t)((uint32_t)(a) - (uint32_t)(b)) < 0)
其被用來檢查TCP序列號小於另一個,考慮到當所述序列號迴繞。它利用了算術環繞的事實,但我無法理解這種情況下的工作原理。
任何人都可以解釋發生了什麼,以及爲什麼上述工作?
這是LWIP的源代碼中的宏:無符號減法在繞回時如何工作?
#define TCP_SEQ_LT(a,b) ((int32_t)((uint32_t)(a) - (uint32_t)(b)) < 0)
其被用來檢查TCP序列號小於另一個,考慮到當所述序列號迴繞。它利用了算術環繞的事實,但我無法理解這種情況下的工作原理。
任何人都可以解釋發生了什麼,以及爲什麼上述工作?
舉一個簡單的4位整數例子,其中a = 5和B = 6每個的二進制表示將現在
a = 0101
b = 0110
當我們減去這些(或採取B的二的補碼,總和與,並添加1),我們得到以下
0101
1001
+ 1
-----
1111
1111等於15(無符號)或-1(簽署,再次使用補翻譯)。通過將這兩個數字轉換爲無符號數,我們確保如果b> a,兩者之間的差異將是一個大的無符號數,並且設置它的最高位。當把這個大的無符號數轉換成它的有符號數時,由於設定的MSB,我們總會得到一個負數。
正如所指出的那樣,當序列號從最大無符號值回到最小值時,宏也會使用上述算法返回最大值爲< min,因此它的用處。
是的,對不起,它會是例如a = 14和b = 1,這應該產生a小於b(或類似的,用於演示包裝情況)。 – nos 2013-04-25 20:12:17
好點,將修改我的答案,包括這個例子。 – ryanbwork 2013-04-25 20:17:11
當我在實踐中對此進行編碼時,當a = 0-> b時,而且兩個值之間的差值大於127(在我的情況下,對於a和b使用兩個無符號字符)後,我會看到負值。這將不準確地報告,如果b = 64和a = 192,a小於b。對於== 192 - > 63這將是真實的。你能在這裏澄清更多嗎? @ryanbwork – ryeager 2015-06-26 20:29:32
因爲在它與零比較之前它首先被轉換爲有符號整數。請記住,從左到右的第一位讀取將確定帶符號數字中的符號,但用於將無符號整數的範圍增加一個額外位。
例如:假設您有一個4位無符號數字。這將意味着1001是17.但是作爲一個有符號的整數,這將是-1。
現在讓我們說我們做了b0010 - b0100。這以b1110結束。未簽名的是14,簽名爲-6。
環繞a將比b大得多。如果我們減去它們,結果也將非常大,即設置其高位。如果我們然後將結果視爲簽署的值,則較大的差異將變爲負數,小於0.
如果您有兩個序列號2G的分隔符,那麼這將不起作用,但這不會發生。
解決它,例如,一個8位數字。 – 2013-04-25 19:53:42
我很想製作一個編譯器,在目標類型簽名時將超出範圍的數字轉換爲17。 – 2013-04-25 20:34:42
@DanielFischer只要你記錄它。 – 2013-04-25 21:22:35