clinuxhtonl

Converting dotted IP to integer using htonl(inet_addr(IP_str)) return negative values for IP Adresses of Class B and C


I am trying to convert dotted IP to integer using htonl(inet_addr(IP_str)).

The problem is the function returns negative results for IP address of class B and C.

here is some of my code (simplified):

int main() {
const char IP1[] = "10.0.0.0";  //Class A
const char IP2[] = "20.0.0.0";  //Class A    
const char IP3[] = "126.0.0.0";  //Class A
const char IP4[] = "128.0.0.0";  //Class B
const char IP5[] = "160.0.0.0";  //Class B
const char IP6[] = "190.0.0.0";  //Class B
const char IP7[] = "193.0.0.0";  //Class C
const char IP8[] = "200.0.0.0";  //Class C

uint32_t integer_ip;
integer_ip = htonl(inet_addr(IP1));
printf("IP1: %s ------> Integer: %d\n",IP1,integer_ip);
integer_ip = htonl(inet_addr(IP2));
printf("IP2: %s ------> Integer: %d\n",IP2,integer_ip);
integer_ip = htonl(inet_addr(IP3));
printf("IP3: %s ------> Integer: %d\n",IP3,integer_ip);   
integer_ip = htonl(inet_addr(IP4));
printf("IP4: %s ------> Integer: %d\n",IP4,integer_ip);
integer_ip = htonl(inet_addr(IP5));
printf("IP5: %s ------> Integer: %d\n",IP5,integer_ip);
integer_ip = htonl(inet_addr(IP6));
printf("IP6: %s ------> Integer: %d\n",IP6,integer_ip);
integer_ip = htonl(inet_addr(IP7));
printf("IP7: %s ------> Integer: %d\n",IP7,integer_ip);
integer_ip = htonl(inet_addr(IP8));
printf("IP8: %s ------> Integer: %d\n",IP8,integer_ip);
return 0;
}

and The resuls:

IP1: 10.0.0.0 ------> Integer: 167772160   
IP2: 20.0.0.0 ------> Integer: 335544320
IP3: 126.0.0.0 ------> Integer: 2113929216
IP4: 128.0.0.0 ------> Integer: -2147483648
IP5: 160.0.0.0 ------> Integer: -1610612736
IP6: 190.0.0.0 ------> Integer: -1107296256
IP7: 193.0.0.0 ------> Integer: -1056964608
IP8: 200.0.0.0 ------> Integer: -939524096

I tested The results on some online tools like this one.

Consider this line of output :

IP5: 160.0.0.0 ------> Integer: -1610612736

-1610612736 is equal to 160.0.0.0 whiles 1610612736 is equal to 96.0.0.0.

The most important requirement for me is speed. I don't want to check each IP if it is in class A or not.

How do i resolve this problem?

Thanks?


Solution

  • Your code invokes undefined behaviour for printing an unsigned integer as a signed.

    To print the stdint.h types, see inttypes.h. Use the PRIu32 macro to print a uint32_t:

    uint32_t u = 42;
    printf("Value: %" PRIu32 "\n", u);
    

    The standard %u conversion type specificer is not guaranteed to be correct, if uint32_t is not typedef unsigned int uint32_t;. For example with 32 bit long and int, it could be typedefed to unsigned of either.

    For hex, use PRIx32 or PRIX32.

    Details:

    The Macros map to a string literal with the conversion specifier appropriate for your platform, which can be "u". Notice the % must be given in the peceeding part. The standard C feature of concatenating adjscent string literals will generate the final format-string. There will be no run-time overhead.