0

我正在尝试使用htonl(inet_addr(IP_str)).

问题是该函数对 B 类和 C 类的 IP 地址返回否定结果。

这是我的一些代码(简化):

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;
}

结果:

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

我在像这样的一些在线工具上测试了结果。

考虑这行输出:

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

-1610612736等于160.0.0.0whiles1610612736等于96.0.0.0.

对我来说最重要的要求是速度。我不想检查每个 IP 是否属于 A 类。

我该如何解决这个问题?

谢谢?

4

4 回答 4

4

您的代码调用未定义的行为以将无符号整数打印为有符号。

要打印stdint.h类型,请参阅inttypes.h。使用PRIu32宏打印uint32_t

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

如果不是,则标准%u转换类型说明符不保证正确。例如,对于 32 位和,它可以被编辑到任何一个。uint32_ttypedef unsigned int uint32_t;longinttypedefunsigned

对于十六进制,使用PRIx32or PRIX32

细节:

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.

于 2017-02-22T14:24:43.343 回答
3

唯一错误的是您的格式字符串。由于这些是无符号数字,因此您应该使用%u而不是%d,假设uint32_t映射到unsigned int您的编译器(除非您的目标是 8 位或 16 位处理器,否则它可能会这样做)。

如果您想确保您的代码可移植到int类型不是 32 位宽的系统,您PRIu32需要PRI*32使用PRIx32定义inttypes.h

您可以使用宏代替格式说明符,如下所示:

printf("IP1: %s ------> Integer: %" PRIu32 "\n",IP1,integer_ip);
于 2017-02-22T14:11:22.590 回答
3

正如其他人所提到的,%d格式说明符用于打印签名的int. 您传递的值是无符号的。使用错误的格式说明符会调用未定义的行为

您需要使用%u格式说明符将值打印为无符号。

更好的是,使用%x格式说明符将值打印为无符号十六进制。这样,每对十六进制字符对应一个字节的 IP 地址,使其更易于阅读。

编辑:

然而,C 标准不保证 anint至少为 32 位。您需要使用PRIu32orPRIx32宏来为 a 获取正确的格式说明符uint32_t

printf("%" PRIx32 "\n", integer_ip);
于 2017-02-22T14:18:04.733 回答
1

htonl返回一个 32 位无符号整数。

用于打印值的格式说明符%d用于有符号整数值。

使用适合数据类型 ( %u) 的格式说明符,值将显示为无符号正数。

于 2017-02-22T14:12:09.097 回答