Hexadecimal Guide: Why Developers Use Base-16 Every Day
What Is Hexadecimal?
Hexadecimal (hex) is a base-16 number system. It uses sixteen distinct symbols: the digits 0 through 9 and the letters A through F. The letters represent decimal values 10 through 15.
| Hex Digit | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Decimal | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
Each position in a hex number represents a power of 16. For example:
2A3 = 2 × 16² + 10 × 16¹ + 3 × 16⁰
= 512 + 160 + 3
= 675 (decimal)
Programmers write hex values with a 0x prefix in most languages (0xFF) or a # prefix in CSS (#FF5733). These prefixes tell the reader and the compiler that the number is base-16, not base-10.
Why Hexadecimal?
Hex exists for one reason: it makes binary readable. One hex digit maps exactly to four binary digits (bits). This means a byte — 8 bits — always becomes exactly two hex digits.
Binary: 1111 1010
Hex: F A
Result: 0xFA
Compare that to the decimal equivalent: 250 tells you nothing about which bits are set. The hex value FA shows you immediately that the high nibble is 1111 and the low nibble is 1010.
This one-to-four mapping is why hex won out over octal (base-8) in modern computing. Octal groups bits in threes, which doesn't align cleanly with 8-bit, 16-bit, or 32-bit boundaries. Hex aligns perfectly with all of them.
Hex in Everyday Programming
CSS Color Values
Every web developer encounters hex daily through CSS colors. A six-digit hex color specifies red, green, and blue channels, each ranging from 00 to FF (0 to 255).
.hot-pink { color: #FF69B4; } /* R=255, G=105, B=180 */
.deep-blue { color: #003366; } /* R=0, G=51, B=102 */
Modern CSS also supports 8-digit hex with an alpha channel:
.semi-transparent { color: #FF573380; } /* 50% opacity */
Memory Addresses and Debugging
When you print a pointer in C, C++, or Rust, the output is hex. Debuggers display memory addresses in hex. Profilers annotate stack traces with hex offsets.
printf("%p", &variable); // Output: 0x7ffd4a3b2c10
Hex makes these addresses scannable. You can quickly spot alignment (addresses ending in 0 are 16-byte aligned) and page boundaries (addresses where multiple high bits change).
Byte Representation
When you inspect raw data — network packets, file headers, binary protocols — you see hex dumps. Tools like xxd, hexdump, and Wireshark display bytes as hex pairs.
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............
00000010: 0200 3e00 0100 0000 0040 0000 0000 0000 ..>......@......
Each pair of hex characters is one byte. If you can read hex, you can spot magic numbers (7f 45 4c 46 = ELF header), string literals, and structure layouts.
Bitmasks and Flags
Hex is the standard way to write bitmasks. Each hex digit controls exactly four bits.
const READ = 0x4; // 0100
const WRITE = 0x2; // 0010
const EXECUTE = 0x1; // 0001
const FULL_ACCESS = READ | WRITE | EXECUTE; // 0x7 (0111)
Conversion Techniques
Hex to Binary (and Back)
The fastest conversion: replace each hex digit with its 4-bit binary equivalent. Memorize this table and you'll never need a calculator.
| Hex | Binary | Hex | Binary |
|---|---|---|---|
| 0 | 0000 | 8 | 1000 |
| 1 | 0001 | 9 | 1001 |
| 2 | 0010 | A | 1010 |
| 3 | 0011 | B | 1011 |
| 4 | 0100 | C | 1100 |
| 5 | 0101 | D | 1101 |
| 6 | 0110 | E | 1110 |
| 7 | 0111 | F | 1111 |
Hex: 3 C F
Binary: 0011 1100 1111
Hex to Decimal
Multiply each digit by its place value and add:
0xB2 = 11 × 16¹ + 2 × 16⁰ = 176 + 2 = 178
For quick mental math, remember these landmarks:
0x10= 160x100= 256 (one byte)0x1000= 4,0960xFFFF= 65,535 (max 16-bit unsigned)
Decimal to Hex
Divide by 16 repeatedly, collecting remainders:
Decimal 43958 → Hex:
43958 ÷ 16 = 2747 remainder 6
2747 ÷ 16 = 171 remainder 11 (B)
171 ÷ 16 = 10 remainder 11 (B)
10 ÷ 16 = 0 remainder 10 (A)
Result: 0xAB B6
Common Pitfalls
Case Sensitivity
Hex digits A–F can be uppercase or lowercase. 0xFF and 0xff are identical. But some systems (particularly CSS) are case-sensitive in other ways, so pick a convention and stick with it. Most style guides prefer uppercase (0xFF, #FF5733).
Leading Zeros Matter
In hex, 0x1 and 0x01 are the same number, but they imply different things. 0x01 suggests a full byte (8 bits). When working with byte-level data, always pad to the correct width: one byte = two hex digits.
Confusing Hex with Decimal
The number 10 means ten in decimal but sixteen in hex. Always check the prefix. A missing 0x or # can cause silent bugs, especially in configuration files.
JavaScript Octal Trap
In JavaScript, a leading zero on an integer literal used to mean octal in sloppy mode. While modern JS uses 0o for octal and 0x for hex, legacy code may still surprise you. Always use explicit prefixes.
0x10 // 16 (hex) — intended
010 // 8 (octal) — likely a mistake
Key Takeaways
- Hexadecimal is base-16, using digits 0–9 and A–F
- One hex digit equals exactly four binary digits — this is why hex replaced octal
- You encounter hex in CSS colors, memory addresses, debug output, and byte dumps
- The hex-to-binary table (16 entries) is worth memorizing for daily programming
- Always use explicit prefixes (
0xor#) to avoid confusion with decimal - Pad hex values to the correct byte width to prevent subtle bugs
Try It Yourself
Convert between hex, binary, octal, and decimal using our free Number Base Converter. Working with CSS colors? Check the Color Converter to translate hex colors to RGB and HSL.