2

i am storing ip address values into a char array(uint8_t) which size is 4 bytes, instead of that i need to store that values into a single integer,how to do that

    uint8_t ip[4];
    str = "192.168.1.1";
    sscanf(str,"%hhu.%hhu.%hhu.%hhu",&ip[0],&ip[1],&ip[2],&ip[3]);

the above code is which i used to store the ip address values into a char(uint8_t) array

Siva Kannan
  • 2,237
  • 4
  • 27
  • 39

3 Answers3

1

Even tough your question is already answered, I liked you problem so much that I decided to solve it and implement a solution for you. Hope this solves your problem:

/**
 * The problem:
 *
 *    1 9 2 . 1 6 8 . 0 0 0 . 0 0 1
 *
 * How to store this in an int (32 bits)?
 *
 * Hum, let's see: 2^8 = 0-255 (stores values from 0 to 255)
 *
 *  2^(8 + 8 + 8 + 8) = 2^32 = sizeof(int) = 4 => nice!
 *
 * We can store four numbers from 0 to 255 in it, great!
 *
 *
 * Draft of solution:
 *
 * int ipaddress = 0; //0x00000000
 *
 * ipaddress = (192 << 32 - 8*1) || (168 << 32 - 8*2) || (0 << 32 - 8*3) || 1;
 *
 * classA_part = (ipaddress & 0xff000000) >> (32 - 8*1)
 * classB_part = (ipaddress & 0xff0000) >> (32 - 8*2)
 * classC_part = (ipaddress & 0xff00) >> (32 - 8*3)
 * classD_part = ipaddress & 0xff
 *
 * Let's implement shall we?!
 */

Initial Solution:

#define UPPER32 24
#define UPPER16 16
#define UPPER8  8

int main(void)
{
    int ipaddr = 192 << UPPER32 | 168 << UPPER16 | 0 << UPPER8 | 1; //192 168 000 001

    printf("ip address: %d.%d.%d.%d\n",
        ((ipaddr & 0xff000000) >> UPPER32) & 0xff,
        (ipaddr & 0xff0000) >> UPPER16,
        (ipaddr & 0xff00) >> UPPER8,
        (ipaddr & 0xff)
    );

    return 0;
}

Notice that, because you are managing the bits to control how you store things in them, you need to shift the bits back to their position in the lowest significant bits so that you actually get your values.

Also be careful with this part ((ipaddr & 0xff000000) >> UPPER32) & 0xff this works in my machine without the & 0xff because my machine is 64 bits and the extended signal of my 64 bits integer is 0, if your machine architecture happened to be 32 bits then this would extend 1 from the bit 31 to the bit 9 which is a negative number and so your 192 would be something else, not even close to 192.

Anyways, by using a final mask of 0xff we are ensuring that nothing more than 0 will be in the bits ranging from 9 to 31 or 63 (x64).

By the way, the output of this will be:

ip address: 192.168.0.1
Program ended with exit code: 0

Continuing, notice that, the code written as it is, can be strange for some, not everybody wants to deal with bits, so a more elegant approach is possible by simplifying my initial solution, check this out:

#define UPPER32 24
#define UPPER16 16
#define UPPER8  8

#define IPADDRESS(a,b,c,d)    (a << UPPER32 | b << UPPER16 | c << UPPER8 | d)
#define IPADDRESS_CLASS_A(ip) (((ip & 0xff000000) >> UPPER32) & 0xff)
#define IPADDRESS_CLASS_B(ip) ((ip & 0xff0000) >> UPPER16)
#define IPADDRESS_CLASS_C(ip) ((ip & 0xff00) >> UPPER8)
#define IPADDRESS_CLASS_D(ip) (ipaddr & 0xff)

#define IPADDRESS_FORMAT       "%d.%d.%d.%d"
#define EXTRACT_IPADDR(ip)     IPADDRESS_CLASS_A(ip), IPADDRESS_CLASS_B(ip), IPADDRESS_CLASS_C(ip), IPADDRESS_CLASS_D(ip)

int main(void)
{
    int ipaddr = IPADDRESS(192,168,0,1); //192 168 000 001
    printf("ip address: " IPADDRESS_FORMAT "\n", EXTRACT_IPADDR(ipaddr));
    return 0;
}

The clean version look better right! Note, the params a,b,c,d refer to the network classes of the ip address (Class A, B, C, D).

Regards.

UPDATE:

To be perfect the user (programmer using this) will not have to bother even about the format of the ip address more than he should, so, I added IPADDRESS_FORMAT macro that contains a string literal with the common ip address format ;) .

João Pinho
  • 3,725
  • 1
  • 19
  • 29
1

Try this bit-shifting approach to parse your array into a single memory location.

uint8_t ip[4];
str = "192.168.1.1";
sscanf(str,"%hhu.%hhu.%hhu.%hhu",&ip[0],&ip[1],&ip[2],&ip[3]);

uint32_t ans = ip[0] << 24 + ip[1] << 16 + ip[2] << 8 + ip[3];
Community
  • 1
  • 1
Soumen
  • 1,068
  • 1
  • 12
  • 18
0

You might be looking for inet_pton. Or you could get away with something like:

uint32_t someint;
uint8_t *ip = (void *)&someint;

And then your sscanf.

ford
  • 10,687
  • 3
  • 47
  • 54
cnicutar
  • 178,505
  • 25
  • 365
  • 392