使用 htonl(inet_addr(IP_str)) return Class B 和 C 的 IP 地址的负值将点分 IP 转换为整数
Converting dotted IP to integer using htonl(inet_addr(IP_str)) return negative values for IP Adresses of Class B and C
我正在尝试使用 htonl(inet_addr(IP_str))
将点分 IP 转换为整数。
问题是函数 returns 对 class 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
我在一些在线工具上测试了结果,例如 this 一个。
考虑这行输出:
IP5: 160.0.0.0 ------> Integer: -1610612736
-1610612736
等于 160.0.0.0
而 1610612736
等于 96.0.0.0.
对我来说最重要的要求是速度。
我不想检查每个 IP 是否在 class A 中。
我该如何解决这个问题?
谢谢?
唯一的问题是您的格式字符串。由于这些是无符号数,您应该使用 %u
而不是 %d
,假设 uint32_t
在您的编译器上映射到 unsigned int
(除非您的目标是8 或 16 位处理器)。
如果您想确保您的代码可移植到 int
类型不是 32 位宽的系统,您需要使用 PRIu32
宏(或另一个 PRI*32
宏,例如 PRIx32
表示十六进制) defined in inttypes.h
您使用宏代替格式说明符,如下所示:
printf("IP1: %s ------> Integer: %" PRIu32 "\n",IP1,integer_ip);
htonl
returns 32 位 无符号 整数。
您用来打印值的格式说明符 %d
适用于 有符号 整数值。
使用适合数据类型 (%u
) 的格式说明符,值将显示为无符号正数。
正如其他人提到的,%d
格式说明符用于打印签名的 int
。您传递的值是无符号的。使用错误的格式说明符调用 undefined behavior.
您需要使用 %u
格式说明符将值打印为无符号。
更好的是,使用 %x
格式说明符将值打印为无符号十六进制。这样,每对十六进制字符对应一个字节的IP地址,更容易阅读。
编辑:
然而,C 标准并不保证 int
至少是 32 位。您需要使用 PRIu32
或 PRIx32
宏来获取 uint32_t
:
的正确格式说明符
printf("%" PRIx32 "\n", integer_ip);
您的代码调用未定义的行为将无符号整数打印为有符号整数。
要打印 stdint.h
类型,请参阅 inttypes.h
。使用 PRIu32
宏打印 uint32_t
:
uint32_t u = 42;
printf("Value: %" PRIu32 "\n", u);
如果 uint32_t
不是 typedef unsigned int uint32_t;
,则不能保证标准 %u
转换类型指定器是正确的。例如,对于 32 位 long
和 int
,它可以 typedef
ed 到 unsigned
中的任何一个。
对于十六进制,使用 PRIx32
或 PRIX32
。
详情:
宏映射到具有适合您平台的转换说明符的字符串文字,可以是 "u"
。请注意,%
必须在前面的部分给出。连接相邻字符串文字的标准 C 功能将生成最终的格式字符串。不会有 运行 时间开销。
我正在尝试使用 htonl(inet_addr(IP_str))
将点分 IP 转换为整数。
问题是函数 returns 对 class 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
我在一些在线工具上测试了结果,例如 this 一个。
考虑这行输出:
IP5: 160.0.0.0 ------> Integer: -1610612736
-1610612736
等于 160.0.0.0
而 1610612736
等于 96.0.0.0.
对我来说最重要的要求是速度。 我不想检查每个 IP 是否在 class A 中。
我该如何解决这个问题?
谢谢?
唯一的问题是您的格式字符串。由于这些是无符号数,您应该使用 %u
而不是 %d
,假设 uint32_t
在您的编译器上映射到 unsigned int
(除非您的目标是8 或 16 位处理器)。
如果您想确保您的代码可移植到 int
类型不是 32 位宽的系统,您需要使用 PRIu32
宏(或另一个 PRI*32
宏,例如 PRIx32
表示十六进制) defined in inttypes.h
您使用宏代替格式说明符,如下所示:
printf("IP1: %s ------> Integer: %" PRIu32 "\n",IP1,integer_ip);
htonl
returns 32 位 无符号 整数。
您用来打印值的格式说明符 %d
适用于 有符号 整数值。
使用适合数据类型 (%u
) 的格式说明符,值将显示为无符号正数。
正如其他人提到的,%d
格式说明符用于打印签名的 int
。您传递的值是无符号的。使用错误的格式说明符调用 undefined behavior.
您需要使用 %u
格式说明符将值打印为无符号。
更好的是,使用 %x
格式说明符将值打印为无符号十六进制。这样,每对十六进制字符对应一个字节的IP地址,更容易阅读。
编辑:
然而,C 标准并不保证 int
至少是 32 位。您需要使用 PRIu32
或 PRIx32
宏来获取 uint32_t
:
printf("%" PRIx32 "\n", integer_ip);
您的代码调用未定义的行为将无符号整数打印为有符号整数。
要打印 stdint.h
类型,请参阅 inttypes.h
。使用 PRIu32
宏打印 uint32_t
:
uint32_t u = 42;
printf("Value: %" PRIu32 "\n", u);
如果 uint32_t
不是 typedef unsigned int uint32_t;
,则不能保证标准 %u
转换类型指定器是正确的。例如,对于 32 位 long
和 int
,它可以 typedef
ed 到 unsigned
中的任何一个。
对于十六进制,使用 PRIx32
或 PRIX32
。
详情:
宏映射到具有适合您平台的转换说明符的字符串文字,可以是 "u"
。请注意,%
必须在前面的部分给出。连接相邻字符串文字的标准 C 功能将生成最终的格式字符串。不会有 运行 时间开销。