C Program to convert IP address to 32-bit long int

An IPv4 address is displayed as four decimal octets separated by dots (e.g., 192.168.1.1) but is stored internally as a single 32-bit unsigned integer. Converting between the dotted-decimal string and the integer form is a fundamental networking operation — inet_addr() in the POSIX socket API does exactly this. Understanding how to do it manually shows you how bit-shifting and bitwise OR combine four byte values into one 32-bit word.

The original post used unions and lacked validation. This rewrite uses explicit bit-shifting with full input validation, and prints the result in decimal, hex, and binary for full clarity.

The Conversion Formula

For address A.B.C.D:

32-bit int = (A << 24) | (B << 16) | (C << 8) | D

Example: 192.168.1.1

192 = 0xC0 → shift left 24 bits → 0xC0000000
168 = 0xA8 → shift left 16 bits → 0x00A80000
  1 = 0x01 → shift left  8 bits → 0x00000100
  1 = 0x01 → no shift           → 0x00000001
                      OR result → 0xC0A80101 = 3,232,235,777

C Program to Convert IP Address to 32-bit Integer

/* Convert IPv4 address to 32-bit unsigned long integer
 * Compile: gcc -ansi -Wall -Wextra ip_to_int.c -o ip_to_int */
#include <stdio.h>

unsigned long ip_to_long(int a, int b, int c, int d)
{
    return ((unsigned long)a << 24) |
           ((unsigned long)b << 16) |
           ((unsigned long)c <<  8) |
            (unsigned long)d;
}

int octet_valid(int v)
{
    return (v >= 0 && v <= 255);
}

int main(void)
{
    int a, b, c, d;
    unsigned long ip_int;

    printf("Enter IPv4 address (e.g. 192.168.1.1): ");
    if (scanf("%d.%d.%d.%d", &a, &b, &c, &d) != 4) {
        printf("Error: invalid format. Use A.B.C.D\n");
        return 1;
    }

    if (!octet_valid(a) || !octet_valid(b) || !octet_valid(c) || !octet_valid(d)) {
        printf("Error: each octet must be 0-255.\n");
        return 1;
    }

    ip_int = ip_to_long(a, b, c, d);

    printf("IP address  : %d.%d.%d.%d\n", a, b, c, d);
    printf("Decimal     : %lu\n", ip_int);
    printf("Hexadecimal : 0x%08lX\n", ip_int);
    printf("Binary      : ");
    {
        int bit;
        for (bit = 31; bit >= 0; bit--) {
            printf("%lu", (ip_int >> bit) & 1);
            if (bit > 0 && bit % 8 == 0) printf(".");
        }
    }
    printf("\n");

    return 0;
}

How to Compile and Run

gcc -ansi -Wall -Wextra ip_to_int.c -o ip_to_int
./ip_to_int

Sample Output

# 192.168.1.1 (private LAN address)
Enter IPv4 address (e.g. 192.168.1.1): 192.168.1.1
IP address  : 192.168.1.1
Decimal     : 3232235777
Hexadecimal : 0xC0A80101
Binary      : 11000000.10101000.00000001.00000001

# 0.0.0.0 (any/unspecified address)
IP address  : 0.0.0.0
Decimal     : 0
Hexadecimal : 0x00000000
Binary      : 00000000.00000000.00000000.00000000

# 255.255.255.255 (broadcast address)
IP address  : 255.255.255.255
Decimal     : 4294967295
Hexadecimal : 0xFFFFFFFF
Binary      : 11111111.11111111.11111111.11111111

# 10.0.0.1 (private class A)
IP address  : 10.0.0.1
Decimal     : 167772161
Hexadecimal : 0x0A000001
Binary      : 00001010.00000000.00000000.00000001

Bit-Shift Breakdown: 192.168.1.1 = 0xC0A80101

Octet Value Hex Shift Result
A = 192 192 0xC0 << 24 0xC0000000
B = 168 168 0xA8 << 16 0x00A80000
C = 1 1 0x01 << 8 0x00000100
D = 1 1 0x01 none 0x00000001
OR all together 0xC0A80101 = 3,232,235,777

Code Explanation

  • unsigned long — IPv4 addresses span 0 to 4,294,967,295 (2³²−1). A signed int can only hold up to 2,147,483,647 (2³¹−1). Using unsigned long avoids overflow for addresses with the high bit set (all addresses with first octet ≥ 128). On 64-bit Linux, unsigned long is 64 bits, so there is no overflow risk.
  • Cast before shifting: (unsigned long)a << 24 — without the cast, shifting an int value left 24 bits could overflow a 32-bit int if a ≥ 128 (the result would need the 32nd bit). Casting to unsigned long first prevents this.
  • Bitwise OR to combine — the | operator combines the four non-overlapping bit fields. Each octet occupies exactly 8 bits in a non-overlapping position, so OR (not addition) is the correct operator here. They produce the same result when non-overlapping, but OR is semantically correct for “placing” values into specific bit positions.
  • Binary output with dot separators — printing a period every 8 bits (bit % 8 == 0) splits the binary output into four octets, matching the visual structure of the dotted-decimal notation.
  • scanf(“%d.%d.%d.%d”) returns 4 — scanf returns the number of items successfully matched. Checking the return value catches formats like “192.168” that would partially match but leave c and d uninitialized.

What This Program Teaches

  • Bit-shifting to build multi-byte values — the same technique packs fields into network packets, image pixels (RGB: 0xRRGGBB), and hardware registers. Left-shift positions a byte; OR places it.
  • Unsigned arithmetic for networking — network values are always unsigned. Using signed int for an IP address causes subtle bugs with addresses where the MSB is 1 (first octet ≥ 128, e.g., 192.x.x.x) because signed right-shift is implementation-defined and signed overflow is undefined behavior.
  • Extracting bits for display(ip_int >> bit) & 1 extracts the value of any single bit. Right-shift to bring the bit to position 0, then AND with 1 to isolate it. This pattern appears in every binary display routine in C.
  • Reversing the conversion — to go back from a 32-bit int to dotted-decimal: A=(ip>>24)&0xFF, B=(ip>>16)&0xFF, C=(ip>>8)&0xFF, D=ip&0xFF.

Related Programs

Recommended book:
The C Programming Language — Kernighan & Ritchie (India) |
(US)
 | 
C Programming: A Modern Approach — K.N. King (India) |
(US)

Practice what you learned: C Aptitude Questions — or try our C Programming Quiz App on Android.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>