2014-07-10 74 views
2

我正在學習創建一個原始數據包,並按照this教程發送它。一切都很有意義,直到我到達生成校驗和的代碼。Checksum和Bitshift

unsigned short csum (unsigned short *buf, int nwords) 
{ 
    unsigned long sum; 
    for (sum = 0; nwords > 0; nwords--) 
    sum += *buf++; 
    sum = (sum >> 16) + (sum & 0xffff); 
    sum += (sum >> 16); 
    return ~sum; 
} 

看起來他總結了緩衝區中的所有單詞。但是當我打到

sum = (sum >> 16) + (sum & 0xffff); 
    sum += (sum >> 16); 

我完全失去了。看起來他把所有的位都移位了,基本上丟棄了除結轉之外的所有位,然後將它加回到原來的總和中?爲什麼需要& 0xfff?畢竟,爲什麼要再添加進位?是因爲可能會有第二次執行?

+1

這是正確的轉變 – prajmus

+0

顯然腦停止工作(X – Wusiji

回答

4

線:

sum = (sum >> 16) + (sum & 0xffff); 

將左和右的16位字的32位整數。它基本上將數字分成兩半,並將兩半加在一起。總和>> 16給你左邊一半,總和& 0xffff給你右邊一半。

然後,當這兩個加在一起,他們可能會溢出。此行:

sum += (sum >> 16); 

將溢出加回到原始數字中。

0

正在計算的校驗和是16位(unsigned short通常是16位),但變量sumunsigned long,因此可能是32位。

所以操作sum >> 16捕獲到和的高位字,所有對單詞總結到16位以上的時間可以容納。然後這與sum & 0xffff混合,這只是總和的低位字。

這樣,總和的所有位都「摺疊」,以便它們對最終結果有貢獻。