2013-07-01 91 views
6

我有什麼辦法檢查32位網絡掩碼是否有效或不使用按位運算符?有效網絡掩碼的c代碼

我必須從msb端檢查'1'是否在連續流中。 例如11111111.0.0.0(255.0.0.0)有效 但11111101.0.0.0(253.0.0.0)不是。

回答

12

首先要做的是檢查網絡掩碼非零(一個討厭的邊緣情況)。鑑於這是好的,你需要採取按位反轉。

uint32_t y = ~x; 

然後添加一個

uint32_t z = y + 1; 

然後,如果x是適當的網絡掩碼,將有最多1位在此設置。

爲了測試這一點,只需和zz - 1,這恰好是y。如果一切正常,結果將爲零,否則爲零。

valid = (z & y) == 0; 
+1

(即將給出相同的答案:-)但是我會使用'unsigned int'或'uint32_t'來避免'z = y + 1'上的未定義溢出行爲。 –

+0

哎呀,是的。大腦今天早上死了,它只是星期一 - 按建議編輯。 –

+0

我有一些不那麼高效的版本,它具有易於理解的優點。你能否解釋_why_這是否有效?即使在紙上塗寫了一些網絡掩碼並在所有值之間寫入所有值,我都無法確定算法背後的數學原理。 – LeSpocky

0

要檢查是否存在無效的子網掩碼,你可以使用下面的簡單算法:

mask & (~mask >> 1) 

這將計算爲1爲一個有效的網絡掩碼無效的子網掩碼和0。

一個有效的網絡掩碼不能在其右邊有一個零。所有零必須在其右邊必須有另一個零,或者位爲0.如果您將一個網絡掩碼的補碼(〜)與其右邊的一個相加,並將其右移一位,你會將網絡掩碼中的一個與網絡掩碼的移位補碼中的一個對齊。並且將這兩個值一起產生一個表示無效網掩碼的值。

如果按照網絡字節順序應用此算法,請務必使用ntohl()將網絡掩碼轉換爲主機字節順序。此外,如果您希望排除它們,則需要對0xffffffff和0x00000000進行特殊檢查。

注意:由於C對運算符的優先級和關聯性規則,算法中顯示的括號不是必需的,但是我已經添加了它們來使代碼更易於理解,以防您不總是記住優先級和關聯性規則。

int is_netmask_valid(uint32_t mask) 
{ 
    if (mask == 0) return 0; 
    if (mask & (~mask >> 1)) { 
     return 0; 
    } else { 
     return 1; 
    } 
}