Tutorial :Integer to IP Address - C



Question:

I'm preparing for a quiz, and I have a strong suspicion I may be tasked with implementing such a function. Basically, given an IP address in network notation, how can we get that from a 32 bit integer into a string in it's dotted decimal notation (something like 155.247.182.83)...? Obviously we can't be using any type of inet functions either...I'm stumped!


Solution:1

Here's a simple method to do it: The (ip >> 8), (ip >> 16) and (ip >> 24) moves the 2nd, 3rd and 4th bytes into the lower order byte, while the & 0xFF isolates the least significant byte at each step.

void print_ip(int ip)  {      unsigned char bytes[4];      bytes[0] = ip & 0xFF;      bytes[1] = (ip >> 8) & 0xFF;      bytes[2] = (ip >> 16) & 0xFF;      bytes[3] = (ip >> 24) & 0xFF;         printf("%d.%d.%d.%d\n", bytes[3], bytes[2], bytes[1], bytes[0]);          }  

There is an implied bytes[0] = (ip >> 0) & 0xFF; at the first step.

Use snprintf() to print it to a string.


Solution:2

You actually can use an inet function. Observe.

main.c:

#include <arpa/inet.h>    main() {      uint32_t ip = 2110443574;      struct in_addr ip_addr;      ip_addr.s_addr = ip;      printf("The IP address is %s\n", inet_ntoa(ip_addr));  }  

The results of gcc main.c -ansi; ./a.out is

The IP address is 54.208.202.125

Note that a commenter said this does not work on Windows.


Solution:3

Another approach:

union IP {      unsigned int ip;      struct {        unsigned char d;        unsigned char c;        unsigned char b;        unsigned char a;      } ip2;  };    ...  char  ips[20];  IP ip;  ip.ip = 0xAABBCCDD;    sprintf(ips, "%x.%x.%x.%x", ip.ip2.a, ip.ip2.b, ip.ip2.c, ip.ip2.d);  printf("%s\n", ips);  


Solution:4

Hint: break up the 32-bit integer to 4 8-bit integers, and print them out.

Something along the lines of this (not compiled, YMMV):

int i = 0xDEADBEEF; // some 32-bit integer  printf("%i.%i.%i.%i",            (i >> 24) & 0xFF,            (i >> 16) & 0xFF,            (i >> 8) & 0xFF,            i & 0xFF);  


Solution:5

This is what I would do if passed a string buffer to fill and I knew the buffer was big enough (ie at least 16 characters long):

sprintf(buffer, "%d.%d.%d.%d",    (ip >> 24) & 0xFF,    (ip >> 16) & 0xFF,    (ip >>  8) & 0xFF,    (ip      ) & 0xFF);  

This would be slightly faster than creating a byte array first, and I think it is more readable. I would normally use snprintf, but IP addresses can't be more than 16 characters long including the terminating null.

Alternatively if I was asked for a function returning a char*:

char* IPAddressToString(int ip)  {    char[] result = new char[16];      sprintf(result, "%d.%d.%d.%d",      (ip >> 24) & 0xFF,      (ip >> 16) & 0xFF,      (ip >>  8) & 0xFF,      (ip      ) & 0xFF);      return result;  }  


Solution:6

#include "stdio.h"    void print_ip(int ip) {     unsigned char bytes[4];     int i;     for(i=0; i<4; i++) {        bytes[i] = (ip >> i*8) & 0xFF;     }     printf("%d.%d.%d.%d\n", bytes[3], bytes[2], bytes[1], bytes[0]);  }    int main() {     int ip = 0xDEADBEEF;     print_ip(ip);     }  


Solution:7

My alternative solution with subtraction :)

void convert( unsigned int addr )  {      unsigned int num[OCTET],               next_addr[OCTET];    int bits = 8;  unsigned int shift_bits;  int i;    next_addr[0] = addr;   shift_bits -= bits;    num[0] = next_addr[0] >> shift_bits;    for ( i = 0; i < OCTET-1; i ++ )  {             next_addr[i + 1] = next_addr[i] - ( num[i] << shift_bits ); // next subaddr      shift_bits -= bits; // next shift      num[i + 1] = next_addr[i + 1] >> shift_bits; // octet  }    printf( "%d.%d.%d.%d\n", num[0], num[1], num[2], num[3] );  }  


Solution:8

From string to int and back

const char * s_ip = "192.168.0.5";  unsigned int ip;  unsigned char * c_ip = (unsigned char *)&ip;  sscanf(s_ip, "%hhu.%hhu.%hhu.%hhu", &c_ip[3], &c_ip[2], &c_ip[1], &c_ip[0]);  printf("%u.%u.%u.%u", ((ip & 0xff000000) >> 24), ((ip & 0x00ff0000) >> 16), ((ip & 0x0000ff00) >> 8), (ip & 0x000000ff));  

%hhu instructs sscanf to read into unsigned char pointer; (Reading small int with scanf)


inet_ntoa from glibc

char *  inet_ntoa (struct in_addr in)  {  unsigned char *bytes = (unsigned char *) &in;  __snprintf (buffer, sizeof (buffer), "%d.%d.%d.%d",  bytes[0], bytes[1], bytes[2], bytes[3]);  return buffer;  }  


Solution:9

void ul2chardec(char*pcIP, unsigned long ulIPN){  int i; int k=0; char c0, c1;  for (i = 0; i<4; i++){      c0 = ((((ulIPN & (0xff << ((3 - i) * 8))) >> ((3 - i) * 8))) / 100) + 0x30;      if (c0 != '0'){ *(pcIP + k) = c0; k++; }      c1 = (((((ulIPN & (0xff << ((3 - i) * 8))) >> ((3 - i) * 8))) % 100) / 10) + 0x30;      if (!(c1 =='0' && c0=='0')){ *(pcIP + k) = c1; k++; }      *(pcIP +k) = (((((ulIPN & (0xff << ((3 - i) * 8)))) >> ((3 - i) * 8))) % 10) + 0x30;      k++;      if (i<3){ *(pcIP + k) = '.'; k++;}  }  *(pcIP + k) = 0; // pcIP should be x10 bytes  

}


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »