views:

1115

answers:

5

Hi guys...

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!

+3  A: 

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);
Yuval A
Uh ... This doesn't compile, is there a function call missing? And the shift counts are all wrong, they seem to think that two hex digits equals four bits. Further, it's better to shift first and mask later, like iWerner.
unwind
Why did this get any votes?
janm
Like I said, it was a quick answer. Fixed the bit-shifting.
Yuval A
Oh Boy! Never write something like 0xDEADBEEF, unless you want to find yourself debugging for hours etc. See http://stackoverflow.com/questions/1556672/most-horrifying-line-of-code-you-have-ever-seen/1556731#1556731
RED SOFT ADAIR
Ray Burns
1) this is just an example, 2) code has now been compiled and tested
Yuval A
+8  A: 

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.

iWerner
Thanks a bunch iWerner!
Kris Richards
So wait, let me ask you thinks...how would I go the other way around then? If I had the string, how could I get back the int?
Kris Richards
To get back from the string to the int you would need to parse the string. i.e. no easy bit-hacking way.
Yuval A
+1  A: 

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);
Nick D
This isn't portable; it depends on sizeof(unsigned) being 4 (like some other answers) and the byte order within an int.
janm
@janm, of course it's not portable. If there is a need for portable code, we can define alternative IP unions to handle more cpu architectures without modifying the *actual* code.
Nick D
The bit shifting approaches are portable, no modifying _actual_ code required. Why introduce a bunch of special cases where there is a shorter, clearer, portable version? Performance? On a modern compiler, I'd be surprised if you could measure a difference (although I haven't checked).And you probably want %d instead of %x.
janm
A: 

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;
}
Ray Burns
+1  A: 
#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);   
}
sthysel