Hexadecimal & Octal

The Programmer's Shorthand for Binary

Introduction: Why More Number Systems?

Binary is the language computers speak, but it's tedious for humans. A 32-bit memory address is 32 digits long in binary. Decimal conversion is slow and obscures bit patterns. Hexadecimal solves this: the same address is just 8 characters, and you can instantly see the underlying bits.

This guide covers two alternative number systems that every programmer should master:

  • Hexadecimal (Base-16): Uses 0-9 and A-F. One hex digit = exactly 4 bits.
  • Octal (Base-8): Uses 0-7. One octal digit = exactly 3 bits.

The Core Insight

16 = 2⁴ and 8 = 2³. This means hex and octal digits map perfectly to groups of binary digits. This isn't coincidence—it's why these number systems exist. They're compact ways to represent binary data.

16 Hex digits (0-F)
4 Bits per hex digit
8 Octal digits (0-7)
3 Bits per octal digit

Hexadecimal Fundamentals

Hexadecimal (often called "hex") is a base-16 number system. Where decimal uses 10 digits and binary uses 2, hexadecimal uses 16 distinct symbols.

The 16 Hexadecimal Digits

Since we only have 10 numeric symbols (0-9), hex borrows the first six letters of the alphabet:

Decimal Hex Binary Decimal Hex Binary
000000881000
110001991001
22001010A1010
33001111B1011
44010012C1100
55010113D1101
66011014E1110
77011115F1111

Case Doesn't Matter

Hexadecimal letters can be uppercase (A-F) or lowercase (a-f). 0xFF and 0xff are the same value. Style guides vary, but uppercase is traditional and lowercase is common in web development.

Counting in Hexadecimal

Counting in hex works just like decimal, but you count to F before carrying:

Counting from 0 to 32 in Hexadecimal

    Decimal:  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
    Hex:      0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F

    Decimal: 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
    Hex:     10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20
                        

Notice: hex "10" = decimal 16, hex "20" = decimal 32, hex "FF" = decimal 255, hex "100" = decimal 256.

Place Value in Base-16

Like decimal, each position in hex represents a power of the base:

Place Values in Hexadecimal

    Position:    3      2      1      0
    Power:      16³    16²    16¹    16⁰
    Value:      4096   256    16     1

    Example: 2B5F in hex

    2 × 16³  =  2 × 4096 =  8192
    B × 16²  = 11 × 256  =  2816
    5 × 16¹  =  5 × 16   =    80
    F × 16⁰  = 15 × 1    =    15
                          -------
                           11103

    2B5F₁₆ = 11103₁₀
                        

Hexadecimal ↔ Binary Conversion

This is where hex truly shines. Each hex digit corresponds to exactly 4 binary digits (bits), making conversion trivial once you memorize the table.

Hex to Binary

Simply replace each hex digit with its 4-bit binary equivalent:

Example: Convert A7F2 to Binary

    A     7     F     2      ← Hex digits
    ↓     ↓     ↓     ↓
   1010  0111  1111  0010    ← 4 bits each

    Result: A7F2₁₆ = 1010011111110010₂
                        

Example: Convert DEADBEEF to Binary

    D     E     A     D     B     E     E     F
    ↓     ↓     ↓     ↓     ↓     ↓     ↓     ↓
   1101  1110  1010  1101  1011  1110  1110  1111

    DEADBEEF₁₆ = 11011110101011011011111011101111₂

    (DEADBEEF is a famous "magic number" in programming)
                        

Binary to Hex

Group binary digits into sets of 4 (from the right), then convert each group:

Example: Convert 110101101011 to Hex

    Original: 110101101011

    Step 1: Group into 4s from the right
            1101 0110 1011

    Step 2: Convert each group
            1101 → D
            0110 → 6
            1011 → B

    Result: 110101101011₂ = D6B₁₆
                        

Example: Convert 10111 to Hex (padding needed)

    Original: 10111 (5 bits)

    Step 1: Pad to multiple of 4 from the left
            0001 0111

    Step 2: Convert each group
            0001 → 1
            0111 → 7

    Result: 10111₂ = 17₁₆
                        

Why Hex is Perfect for Binary

The power of hex is that 16 = 2⁴. This means:

  • 1 hex digit = 4 bits (a "nibble")
  • 2 hex digits = 8 bits (a byte)
  • 4 hex digits = 16 bits (a word on many systems)
  • 8 hex digits = 32 bits (a dword)
  • 16 hex digits = 64 bits (a qword)

The Practical Advantage

A 32-bit memory address in binary: 11000000101010000000000100000001 (32 digits, impossible to read). In hex: C0A80101 (8 digits, easy to read). That's the same address—192.168.1.1 in IP notation.

Hexadecimal ↔ Decimal Conversion

Hex to Decimal

Multiply each digit by its place value and sum:

Example: Convert 3E8 to Decimal

    3E8₁₆

    3 × 16² = 3 × 256 = 768
    E × 16¹ = 14 × 16 = 224
    8 × 16⁰ = 8 × 1   =   8
                       -----
                        1000

    3E8₁₆ = 1000₁₀ ✓

    (3E8 = 1000 is used as HTTP "OK" and common test value)
                        

Example: Convert FF to Decimal

    FF₁₆

    F × 16¹ = 15 × 16 = 240
    F × 16⁰ = 15 × 1  =  15
                       ----
                        255

    FF₁₆ = 255₁₀

    (Maximum value for one byte)
                        

Decimal to Hex

Repeatedly divide by 16, keeping the remainders:

Example: Convert 500 to Hex

    500 ÷ 16 = 31 remainder 4   → 4
     31 ÷ 16 =  1 remainder 15  → F
      1 ÷ 16 =  0 remainder 1   → 1

    Read remainders bottom to top: 1F4₁₆

    Verify: 1×256 + 15×16 + 4×1 = 256 + 240 + 4 = 500 ✓
                        

Example: Convert 65535 to Hex

    65535 ÷ 16 = 4095 remainder 15 → F
     4095 ÷ 16 =  255 remainder 15 → F
      255 ÷ 16 =   15 remainder 15 → F
       15 ÷ 16 =    0 remainder 15 → F

    65535₁₀ = FFFF₁₆

    (Maximum value for 16 bits / 2 bytes)
                        

Octal Fundamentals

Octal (base-8) was more popular in early computing when computer word sizes were often multiples of 3 (12, 24, 36 bits). It's less common now but still appears in specific contexts.

The 8 Octal Digits

Decimal Octal Binary
00000
11001
22010
33011
44100
55101
66110
77111

Note: Octal only uses digits 0-7. The digits 8 and 9 do not exist in octal!

Octal ↔ Binary Conversion

Each octal digit = exactly 3 binary bits:

Example: Convert 752 (octal) to Binary

    7     5     2      ← Octal digits
    ↓     ↓     ↓
   111   101   010     ← 3 bits each

    752₈ = 111101010₂
                        

Example: Convert 11010110 (binary) to Octal

    Original: 11010110

    Group into 3s from right:
    011  010  110
     ↓    ↓    ↓
     3    2    6

    11010110₂ = 326₈
                        

Where Octal is Still Used

Unix File Permissions

The most common use of octal today. Permissions are three groups of 3 bits (owner/group/other), each with read/write/execute flags. chmod 755 means rwxr-xr-x (111 101 101 in binary).

C/C++ Octal Literals

Numbers starting with 0 are octal in C: int x = 0755; is 493 in decimal. This is a common source of bugs when people write 0-prefixed numbers expecting decimal!

Escape Sequences

Some escape sequences use octal: \101 is 'A' (65 decimal = 101 octal). Though hex escapes (\x41) are more common now.

Unix Permissions Example

    Permission: rwxr-xr-x

    rwx = 111 = 7  (read+write+execute for owner)
    r-x = 101 = 5  (read+execute for group)
    r-x = 101 = 5  (read+execute for others)

    Octal: 755
    Command: chmod 755 myfile

    Another example:
    rw-r--r-- = 110 100 100 = 644 (common for files)
    rwxr-xr-x = 111 101 101 = 755 (common for executables)
                        

Number System Notation

To avoid confusion between number systems, various notation conventions exist:

Convention Binary Octal Decimal Hexadecimal
Subscript 1010₂ 12₈ 10₁₀ A₁₆
Prefix (common) 0b1010 012 10 0xA
Suffix 1010b 12o 10d Ah
Hash prefix #0A (CSS)
Ampersand &O12 &HA

Language-Specific Notations

Language Binary Octal Hexadecimal
C/C++/Java 0b1010 (C++14+) 012 0xA or 0XA
Python 0b1010 0o12 0xA
JavaScript 0b1010 0o12 0xA
Assembly (Intel) 1010b 12o or 12q 0Ah or 0xA
CSS #RRGGBB

The Dangerous Octal Prefix

In C/C++, a leading zero makes a number octal. int x = 010; assigns 8, not 10! This trips up programmers who use leading zeros for alignment. Python 3 changed to 0o prefix for octal to avoid this confusion.

Arithmetic in Hexadecimal

While you'll rarely need to do hex arithmetic by hand, understanding it deepens your number system fluency.

Hexadecimal Addition

Add digits, carrying when the sum exceeds F (15):

Example: 3A + 2F

        3 A
      + 2 F
      -----

    Position 0: A + F = 10 + 15 = 25
                25 = 16 + 9 = 10₁₆ (write 9, carry 1)

    Position 1: 3 + 2 + 1(carry) = 6

    Result: 3A + 2F = 69₁₆

    Verify: 3A = 58, 2F = 47, 58 + 47 = 105 = 69₁₆ ✓
                        

Example: FF + 1

        F F
      +   1
      -----

    Position 0: F + 1 = 15 + 1 = 16 = 10₁₆ (write 0, carry 1)
    Position 1: F + 0 + 1(carry) = 16 = 10₁₆ (write 0, carry 1)
    Position 2: 0 + 0 + 1(carry) = 1

    Result: FF + 1 = 100₁₆ = 256₁₀

    (This is exactly like 99 + 1 = 100 in decimal)
                        

Hexadecimal Subtraction

Example: 5C - 2E

        5 C
      - 2 E
      -----

    Position 0: C - E = 12 - 14 (need to borrow!)
                Borrow 1 from position 1: 12 + 16 = 28
                28 - 14 = 14 = E

    Position 1: 5 - 1(borrowed) - 2 = 2

    Result: 5C - 2E = 2E₁₆

    Verify: 5C = 92, 2E = 46, 92 - 46 = 46 = 2E₁₆ ✓
                        

Practical Tip

In practice, programmers convert to decimal or binary, do the math, then convert back. Or they just use a calculator! Hand calculation is mainly useful for building intuition.

Memory Addresses and Hexadecimal

Memory addresses are almost always displayed in hexadecimal. This is the primary reason every programmer must be fluent in hex.

Why Hex for Addresses?

  • Compactness: 8 hex digits vs. 32 binary or up to 10 decimal digits
  • Bit visibility: You can see the binary pattern directly
  • Alignment: Powers of 2 have recognizable patterns in hex
  • Convention: It's what debuggers, disassemblers, and documentation use

Common Address Patterns

Address Significance
0x00000000 Null pointer / start of address space
0x00400000 Typical Windows executable base address
0x7FFFFFFF End of 32-bit user space (2GB)
0x80000000 Start of kernel space (32-bit Windows)
0xDEADBEEF Magic number to mark uninitialized memory
0xCAFEBABE Java class file magic number
0xFFFFFFFF Maximum 32-bit address / -1 in signed

Reading a Memory Dump

Typical Memory Dump Format

Address    Hex Content                        ASCII
-------    -------------------------------    ----------------
0x1000     48 65 6C 6C 6F 20 57 6F 72 6C 64   Hello World
0x100B     21 0A 00 00 00 00 00 00 00 00 00   !...........
0x1016     01 02 03 04 05 06 07 08 09 0A 0B   ............

Each pair of hex digits = one byte
0x48 = 'H', 0x65 = 'e', 0x6C = 'l', etc.
                        

Pointer Arithmetic

When debugging, you'll often need to calculate memory offsets:

Example: Finding Array Element

    Array starts at: 0x7FFF0100
    Element size: 4 bytes (int)
    Want element index: 5

    Address = 0x7FFF0100 + (5 × 4)
            = 0x7FFF0100 + 20
            = 0x7FFF0100 + 0x14
            = 0x7FFF0114

    Element 5 is at address 0x7FFF0114
                        

Color Codes: RGB in Hexadecimal

One of the most common uses of hexadecimal is representing colors in web development and graphics.

RGB Color Model

Colors are specified as Red, Green, Blue intensities, each from 0-255 (one byte):

Hex Color Format: #RRGGBB

    #FF0000 = Red: FF (255), Green: 00 (0), Blue: 00 (0) = Pure Red
    #00FF00 = Red: 00 (0), Green: FF (255), Blue: 00 (0) = Pure Green
    #0000FF = Red: 00 (0), Green: 00 (0), Blue: FF (255) = Pure Blue
    #FFFFFF = All maximum = White
    #000000 = All zero = Black
    #808080 = All half (128) = Gray
                        

Common Color Values

Color Hex Code RGB Values
Red#FF0000255, 0, 0
Green (Lime)#00FF000, 255, 0
Blue#0000FF0, 0, 255
Yellow#FFFF00255, 255, 0
Magenta#FF00FF255, 0, 255
Cyan#00FFFF0, 255, 255
Orange#FFA500255, 165, 0
Purple#800080128, 0, 128

Shorthand Notation

CSS allows 3-digit shorthand when each pair is the same digit:

Shorthand Examples

    #FFF = #FFFFFF (white)
    #000 = #000000 (black)
    #F00 = #FF0000 (red)
    #0F0 = #00FF00 (green)
    #00F = #0000FF (blue)
    #ABC = #AABBCC (light grayish blue)

    Rule: Each digit is doubled
    #XYZ becomes #XXYYZZ
                        

RGBA: Adding Transparency

A fourth byte can specify alpha (transparency):

RGBA Format: #RRGGBBAA

    #FF000080 = Red at 50% opacity
    #0000FF40 = Blue at 25% opacity
    #000000CC = Black at 80% opacity

    Alpha: 00 = fully transparent, FF = fully opaque
    80₁₆ = 128₁₀ = 50% opacity
                        

Hexadecimal in Programming

Hex appears constantly in programming. Here are the most common uses:

Bit Manipulation

Common Bitmasks

    // Check if bit 3 is set
    if (value & 0x08) { ... }

    // Set bit 5
    value |= 0x20;

    // Clear bit 7
    value &= ~0x80;  // OR: value &= 0x7F;

    // Extract low nibble
    low = value & 0x0F;

    // Extract high nibble
    high = (value >> 4) & 0x0F;

    Why hex? 0x08 shows "bit 3" clearly:
    0x08 = 0000 1000
              ↑ bit 3
                        

Magic Numbers and Constants

Hex Value Meaning Usage
0xDEADBEEF "Dead beef" Uninitialized memory marker
0xCAFEBABE "Cafe babe" Java class file signature
0xFEEDFACE "Feed face" macOS Mach-O signature
0xBAADF00D "Bad food" Windows LocalAlloc marker
0x8BADF00D "Ate bad food" Apple watchdog timeout
0x7F454C46 ".ELF" ELF executable signature
0x504B0304 "PK.." ZIP file signature

Character Codes

ASCII in Hexadecimal

    Common ASCII values:

    0x00 = NUL (null terminator)
    0x0A = LF (line feed, \n)
    0x0D = CR (carriage return, \r)
    0x20 = Space
    0x30-0x39 = '0'-'9' (digits)
    0x41-0x5A = 'A'-'Z' (uppercase)
    0x61-0x7A = 'a'-'z' (lowercase)

    Lowercase = Uppercase + 0x20
    'A' (0x41) + 0x20 = 'a' (0x61)
                        

Network and Protocol Data

Ethernet Frame in Hex

    MAC Address: 00:1A:2B:3C:4D:5E

    Each pair is one byte:
    00 1A 2B 3C 4D 5E = 6 bytes

    IP Address: 192.168.1.1
    In hex: C0.A8.01.01

    192 = 0xC0
    168 = 0xA8
    1   = 0x01
    1   = 0x01
                        

Working with Hex Editors

Hex editors display file contents as hexadecimal bytes, allowing you to inspect and modify binary data directly.

Popular Hex Editors

  • HxD (Windows) - Free, fast, full-featured
  • Hex Fiend (macOS) - Free, native Mac app
  • xxd (Unix) - Command-line hex dump tool
  • hexdump (Unix) - Another command-line option
  • VS Code Hex Editor - Extension for VS Code

Reading Hex Editor Output

Typical Hex Editor Display

Offset    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F  ASCII
--------  -----------------------------------------------  ----------------
00000000  89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52  .PNG........IHDR
00000010  00 00 01 00 00 00 01 00 08 02 00 00 00 D3 10 3F  ...............?
00000020  31 00 00 00 01 73 52 47 42 00 AE CE 1C E9 00 00  1....sRGB.......

Components:
- Offset: Position in file (hex)
- Hex bytes: 16 bytes per row
- ASCII: Printable characters (. for non-printable)

The 89 50 4E 47 at start identifies this as a PNG image.
                        

File Signatures (Magic Numbers)

Hex Signature File Type
89 50 4E 47PNG image
FF D8 FFJPEG image
47 49 46 38GIF image
50 4B 03 04ZIP archive
25 50 44 46PDF document
4D 5AWindows EXE/DLL
7F 45 4C 46Linux ELF executable
1F 8BGZIP compressed

Why File Signatures Matter

File extensions can be changed, but signatures can't be faked. Security tools check signatures to identify file types regardless of extension. A malicious "image.jpg" might have an EXE signature (4D 5A), revealing it as an executable.

Practice Problems with Solutions

Conversion Problems

Problem 1: Convert 0xBEEF to binary and decimal

Show Solution
    Binary:
    B    E    E    F
    1011 1110 1110 1111

    BEEF₁₆ = 1011111011101111₂

    Decimal:
    B × 16³ = 11 × 4096 = 45056
    E × 16² = 14 × 256  =  3584
    E × 16¹ = 14 × 16   =   224
    F × 16⁰ = 15 × 1    =    15
                         ------
                          48879

    BEEF₁₆ = 48879₁₀ ✓
                            

Problem 2: Convert 11111010 binary to hex and octal

Show Solution
    Hex (group by 4):
    1111 1010
    F    A

    11111010₂ = FA₁₆ ✓

    Octal (group by 3):
    011 111 010
    3   7   2

    11111010₂ = 372₈ ✓
                            

Problem 3: Convert decimal 1000 to hex

Show Solution
    1000 ÷ 16 = 62 remainder 8 → 8
      62 ÷ 16 =  3 remainder 14 → E
       3 ÷ 16 =  0 remainder 3 → 3

    1000₁₀ = 3E8₁₆ ✓
                            

Practical Problems

Problem 4: What Unix permission is rwxr-x--- in octal?

Show Solution
    rwx = 111 = 7
    r-x = 101 = 5
    --- = 000 = 0

    rwxr-x--- = 750₈ ✓
                            

Problem 5: What color is #FF8C00?

Show Solution
    R: FF = 255 (maximum)
    G: 8C = 140 (about 55%)
    B: 00 = 0 (none)

    High red + medium green + no blue = Orange

    Specifically, this is "Dark Orange" in CSS.
                            

Problem 6: Add 0x3A + 0x5F without converting to decimal

Show Solution
        3 A
      + 5 F
      -----

    Position 0: A + F = 10 + 15 = 25
                25 - 16 = 9, carry 1

    Position 1: 3 + 5 + 1 = 9

    Result: 99₁₆

    Verify: 0x3A = 58, 0x5F = 95
            58 + 95 = 153
            153 = 9×16 + 9 = 0x99 ✓
                            

Summary

You've now mastered hexadecimal and octal—the essential tools for working with binary data in a human-readable format.

  • Hexadecimal (base-16) uses 0-9 and A-F; each digit = 4 bits
  • Octal (base-8) uses 0-7; each digit = 3 bits
  • Conversion between hex/octal and binary is trivial once you know the digit mappings
  • Hex is essential for memory addresses, color codes, and debugging
  • Octal survives mainly in Unix file permissions
  • File signatures help identify file types regardless of extension

These skills will serve you daily as a programmer, whether you're debugging memory issues, working with network protocols, designing web interfaces, or analyzing binary files.