Hi,

I have a requirement to convert a unsigned int 32 value to a IP address dotted format.
Can this be done using a C function?

Requirement:
Eg: Input value = 3232235691
i.e
11000000 10101000 00000000 10101011
Converted to LAN Ip - 192.168.0.171

Please help.(Newbie to C programming)

okay, well before you get into the gory details of using winsock for network programming with C, you should understand the basic exercise of converting one number system to another number system, using bitwise operators.

consider the address:
10.1.10.127

if you convert each octet to a binary group

10         1        10       127
00001010  00000001  00001010  01111111

then the 32 bit binary number as one single integer has the decimal value.

1010000000010000101001111111(bin) = 167840383(dec)

you can programmatically convert between these number systems in either direction. consider (and understand) this snippet:

unsigned int  ipAddress = 167840383;
unsigned char octet[4]  = {0,0,0,0};

for (i=0; i<4; i++)
{
    octet[i] = ( ipAddress >> (i*8) ) & 0xFF;
}

now you have the four octets as unsigned chars in the "octet[]" array (char is just an 8-bit integer), and you can print them in the decimal dot format:

printf("%d.%d.%d.%d\n",octet[3],octet[2],octet[1],octet[0]);

.

jephthah's way is the safest and most portable once you fix the nonportable assumptions:

#include <stdio.h>

#if __STDC_VERSION == 199901L
#include <stdint.h>
#else
/* change to fit the compiler */
typedef unsigned char uint8_t;
typedef unsigned long uint32_t;
#endif

#define IPV4

#if defined(IPV4)
#define NBYTES 4
#elif defined(IPV6)
#error IPV6 not supported
#else
#error No valid IP version protocol defined
#endif

int main()
{
    uint32_t ipAddress = 167840383;
    uint8_t  octet[NBYTES];
    int x;

    for (x = 0; x < NBYTES; x++)
    {
        octet[x] = (ipAddress >> (x * 8)) & (uint8_t)-1;
    }

    for (x = NBYTES - 1; x >= 0; --x)
    {
        printf("%d", octet[x]);

        if (x > 0) printf(".");
    }

    printf("\n");

    return 0;
}

The biggest assumption jephthah's code makes is that unsigned int is 4 bytes and a byte is 8 bits. If they are, the math works out, but if they are not, bad things can happen.

I fixed those two assumptions by using the explicit sized types from C99's <stdint.h>, and for everyone playing at home without a C99 compiler, I defined uint32_t and uint8_t as an example only. Don't come crying to me if unsigned char isn't 8 bits on your computer. ;)

There is another way that's easier to get right. Instead of playing with bit operators, make a union with two members. The first member is a 32 bit type and the second is an array of 4 8 bit types. They take the same memory so when you assign the whole number to the 32 byte type, the array has each of the bytes for it.

#include <stdio.h>

#if __STDC_VERSION == 199901L
#include <stdint.h>
#else
/* change to fit the compiler */
typedef unsigned char uint8_t;
typedef unsigned long uint32_t;
#endif

#define IPV4

#if defined(IPV4)
#define NBYTES 4
#elif defined(IPV6)
#error IPV6 not supported
#else
#error No valid IP version protocol defined
#endif

int main()
{
    union
    {
        uint32_t obj;
        uint8_t  bytes[NBYTES];
    } b;
    int x;

    b.obj = 167840383;

    for (x = NBYTES - 1; x >= 0; --x)
    {
        printf("%d", b.bytes[x]);

        if (x > 0) printf(".");
    }

    printf("\n");

    return 0;
}

One more time. I defined uint32_t and uint8_t as an example only. Don't come crying to me if unsigned char isn't 8 bits on your computer or unsigned long has padding bits that break the code. ;)

Comments
Great code there...
a bit overly pedantic ... but solid

nice code.... a bit of pedantic tangent, perhaps, but i'll agree: my assumption of 8 bit chars was overly simplistic and may be incorrect for some environments.

still, the point was not to write bulletproof code, but to merely illustrate basic bit shift and mask techniques before getting into the structures of the winsock or sockets library

because i dont know anyone who would use the above method (my version or yours) to write a real network program. they'd use conditional compilation of the standard socket libraries that have been in use for 20-odd years.


.

my assumption of 8 bit chars was overly simplistic and may be incorrect for some environments.

Yeah right. 8 bit bytes are the norm now. If you are using hardware that doesn't have them, you probably don't need to be taught how to fix code that assumes them. It's like ASCII. The folks using EBCDIC already know what to look for and how to fix it. ;)

The big kicker was assuming that unsigned int was 32 bits. I think it's more probable that ad hoc code for bit fiddling will find its way to a computer where ints are 16 bits than a computer with something other than 8 bit bytes. That's why I changed your unsigned int to unsigned long. unsigned long is always at least 32 bits.

the point was not to write bulletproof code, but to merely illustrate basic bit shift and mask techniques

Add union tricks and basic concern over portability to the list of jephthah/Tommy tag team teaching goodness. :) I took the time to do it well because this stuff can be used for more than just formatting IP addresses.

Besides, everyone can learn from good code. Do you know where I can find some? ;)

jephthah's code works fine for me.
Thanks a lot...appreciate your help
Also appreciate Tom's analyses

/// <summary>Convert an UInt32 into an IP String</summary>
/// <param name="UIntIP">UInt32 to convert into a String.</param>
/// <returns>String equivilant:\nFormat: "xxx.xxx.xxx.xxx"</returns>
public String UInt32ToIPAdd(UInt32 UIntIP)
{
    return (UIntIP >> 24) + "." + ((UIntIP >> 16) & 0xff) + "." + ((UIntIP >> 8) & 0xff) + "." + (UIntIP & 0xff);
}

Edited 6 Years Ago by dmadden: C# way if needed...

This article has been dead for over six months. Start a new discussion instead.