How subnet masks work at the binary level — the bitwise AND that separates network from host, the binary structure of /24, /16, /8, and why every subnetting problem is really a bitwise operation.
A subnet mask is a 32-bit number that tells a router or a host which part of an IP address belongs to the network and which part belongs to the host. Every device on an IP network needs one, and the way it works is pure bitwise logic. When I first started working with networks, I found that the concept clicked only once I stopped thinking of subnet masks as dotted-decimal numbers and started thinking of them as binary bitmasks — because that's exactly what they are.
A subnet mask looks like an IP address — 255.255.255.0, for example — but it is not an address. It is a pattern of bits: every bit that is 1 means "this bit in the IP identifies the network," and every bit that is 0 means "this bit in the IP identifies a specific host on that network." In binary, 255.255.255.0 is 11111111.11111111.11111111.00000000. The first three octets (24 bits) are all ones — they define the network. The last octet is all zeros — it defines the host. I've explained this to dozens of junior engineers over the years, and the single best way to check understanding is to watch them perform one bitwise AND by hand.
I calculate subnet masks in my head often when setting up VPN tunnels and Docker networks. A /24 is 255.255.255.0 (24 leading ones), a /16 is 255.255.0.0 — once you understand that the CIDR notation is simply the count of consecutive 1-bits, the rest is easy.
The bitwise AND between an IP address and its subnet mask always yields the network address. Anything beyond that zeros pattern belongs to the host. This single operation is what every router performs on every packet, at wire speed, in hardware.
The router's forwarding decision boils down to a single bitwise AND. When a packet arrives with a destination IP, the router ANDs that IP with the subnet mask configured on each interface. If the result matches the interface's network address, the packet belongs to that subnet and is forwarded locally. If no match is found, the packet goes to the default gateway.
Let me walk through this with a concrete example. When I configure a device on 192.168.1.0/24, I assign it an IP like 192.168.1.37 with mask 255.255.255.0. To determine the network portion, I align the IP and mask bit by bit and apply AND:
Every bit where the mask has a 1 passes through unchanged. Every bit where the mask has a 0 is forced to 0. The result — 192.168.1.0 — is the network address. The portion that got zeroed out — 00100101 or decimal 37 — is the host identifier. I routinely use this mental model when troubleshooting connectivity: if two devices have the same network address after ANDing with their mask, they are on the same broadcast domain and should be able to talk directly without a router.
CIDR (Classless Inter-Domain Routing) notation — /24, /16, /8 — is simply a shorthand for how many leading 1s are in the subnet mask's 32-bit binary form. I find CIDR far more intuitive than dotted-decimal once you internalize the binary mapping, because the number tells you exactly how many bits belong to the network.
The host count is determined by the remaining bits. If the mask has N zeros, there are 2N - 2 usable host addresses (subtracting the network address where all host bits are 0 and the broadcast address where all host bits are 1). A /24 has 8 host bits, so 28 - 2 = 254 usable addresses. A /30 has only 2 host bits, giving exactly 2 usable addresses — the minimum for a point-to-point link. I memorize these by keeping the binary pattern in mind rather than trying to remember decimal numbers.
When you need to divide a network into smaller subnets — for separate departments, VLANs, or cloud VPCs — you are performing a bitwise operation on the mask itself. You borrow bits from the host portion and move them into the network portion, increasing the prefix length and creating smaller subnets.
Let me walk through a scenario I encounter often. You have 10.0.0.0/16 and need 8 subnets of equal size. To get 8 subnets, you need 3 additional bits (23 = 8). Borrow 3 bits from the host side, and the new mask becomes /19 — that is 16 + 3 = 19 ones.
The borrowed bits become part of the network address in the third octet. Because the mask's third octet is now 11100000 (224 in decimal), the subnet increments by 32 (which is 25, the value of the lowest borrowed bit). I've watched many engineers struggle with this until they write out the binary — once you see the bits marching in groups of three across the octet boundary, the "magic number" method of subnetting makes perfect sense.
The "block size" or "subnet increment" is 256 - (non-255 octet of mask). For a mask of 255.255.224.0, the varying octet is 224, so the increment is 256 - 224 = 32. This works because 224 = 11100000 in binary, and 32 = 00100000 — the lowest 1 bit. Use our programming calculator to convert between decimal and binary as you practice.
Over the years, I've debugged countless subnet mask misconfigurations, and the root cause almost always traces back to a binary mismatch. Here are the three most common pitfalls I've seen, and how to spot them using bitwise reasoning.
Two devices on the same switch might have IPs in the same range but different subnet masks. Device A has 192.168.1.50/24 and device B has 192.168.1.60/28. Device A thinks the network is 192.168.1.0 with 254 hosts. Device B thinks the network is 192.168.1.48 with 14 hosts. Device A will ARP for 192.168.1.60 directly; device B, computing the network as 192.168.1.60 AND 255.255.255.240, gets 192.168.1.48 and may ARP for its gateway instead. The result? Intermittent connectivity that looks like a cable problem. I always reach for the binary representation of the mask first when I see this pattern.
The default gateway must be on the same network as the host. If the gateway's IP AND the host's mask does not equal the host's network address, traffic cannot leave the subnet. This is a pure bitwise check that takes two seconds with a calculator.
In cloud environments (AWS VPC, Azure vNet), overlapping subnets cause routing nightmares. Two VPCs peered with 10.0.0.0/16 and 10.0.128.0/17 overlap because the /16 encompasses addresses that the /17 claims. The AND operation reveals this: 10.0.0.0 AND 255.255.0.0 = 10.0.0.0 and 10.0.128.0 AND 255.255.128.0 = 10.0.0.0 — they share the same /16 base, so VPN tunnels will have ambiguous routes. I plan VPC CIDRs on a binary spreadsheet these days to avoid this exact problem.
Use our interactive calculators to experiment with subnet masks and bitwise operations. Enter any IP and mask combination and see the binary result update in real time.
Bitwise AND between an IP address and its subnet mask zeroes out the host bits, leaving only the network portion. For example, 192.168.1.37 (11000000.10101000.00000001.00100101) AND 255.255.255.0 (11111111.11111111.11111111.00000000) = 192.168.1.0 (11000000.10101000.00000001.00000000). This is how routers determine which network a packet belongs to.
/24 means the first 24 bits of the subnet mask are set to 1 and the remaining 8 bits are 0. In binary, 255.255.255.0 = 11111111.11111111.11111111.00000000. The 24 ones represent the network portion, and the 8 zeros represent the host portion, allowing for 254 usable host addresses.
A subnet mask written in CIDR notation like /24 means N bits of ones followed by (32-N) bits of zeros. Group those bits into four 8-bit octets. For /24: 24 ones + 8 zeros = 11111111.11111111.11111111.00000000 = 255.255.255.0. For /16: 16 ones + 16 zeros = 11111111.11111111.00000000.00000000 = 255.255.0.0. For /8: 8 ones + 24 zeros = 11111111.00000000.00000000.00000000 = 255.0.0.0.
The network address is the result of ANDing the IP with the subnet mask — it has all host bits set to 0. The broadcast address has all host bits set to 1. For a /24 network 192.168.1.0/24, the network address is 192.168.1.0 and the broadcast address is 192.168.1.255. Host addresses 192.168.1.1 through 192.168.1.254 are available for assignment.
Absolutely. Subnet masks can have any contiguous stretch of 1s followed by 0s. Common ones include 255.255.255.0 (/24), 255.255.255.128 (/25), 255.255.255.192 (/26), 255.255.255.240 (/28), and non-octet-aligned masks like 255.255.254.0 (/23) which gives 510 usable hosts. The key is that subnet mask bits are always contiguous ones from the left.