An IP Subnet is defined with two parts, a network and a prefix-length or mask.
For example 192.168.0.0/16
(or, 192.168.0.0/255.255.0.0
).
An IP address like 192.168.1.1
is said to match this subnet because,
(192.168.1.1 & 255.255.0.0) == 192.168.0.0
I am interested in what might be called the inverse of a subnet
which is described like this,
For a given SubnetA (say, NetworkA / MaskA),
The inverse of SubnetA is the list of k subnets, such that,If an IP address A, matches SubnetA,
A will not match any of these k subnets, and
Every IP address B that does not match SubnetA,
will match exactly 1 of these k subnets.
Code is not necessary, I am interested in a correct and optimal method.
I have the optimized answer noted for reference in this code snippet.
unsigned int network; // 32-bit network. Say (192.168.0.0 or 0xC0A80000)
unsigned int mask; // 32-bit mask (0xFFFF0000 for the example case)
i = 0; // to iterate over the network bits
do {
bitmask = (unsigned int)(0x80000000 >> i)
invmask = (unsigned int)(0xFFFFFFFF << (31-i));
invnet = (invmask & network) ^ bitmask;
printSubnet(invnet, invmask); // this stores/prints the subnet
} while (mask && i<32); // only while we have valid mask
Accepted Rafał's answer since he also got it right first.
Here is the inverse for 192.168.0.0/16
, to check correctness.
[1] 0.0.0.0 / 128.0.0.0 ; 00000000
[2] 128.0.0.0 / 192.0.0.0 ; 80000000
[3] 224.0.0.0 / 224.0.0.0 ; e0000000
[4] 208.0.0.0 / 240.0.0.0 ; d0000000
[5] 200.0.0.0 / 248.0.0.0 ; c8000000
[6] 196.0.0.0 / 252.0.0.0 ; c4000000
[7] 194.0.0.0 / 254.0.0.0 ; c2000000
[8] 193.0.0.0 / 255.0.0.0 ; c1000000
[9] 192.0.0.0 / 255.128.0.0 ; c0000000
[10] 192.192.0.0 / 255.192.0.0 ; c0c00000
[11] 192.128.0.0 / 255.224.0.0 ; c0800000
[12] 192.176.0.0 / 255.240.0.0 ; c0b00000
[13] 192.160.0.0 / 255.248.0.0 ; c0a00000
[14] 192.172.0.0 / 255.252.0.0 ; c0ac0000
[15] 192.170.0.0 / 255.254.0.0 ; c0aa0000
[16] 192.169.0.0 / 255.255.0.0 ; c0a90000