我正在尝试使用htonl(inet_addr(IP_str))
将点分IP转换为整数。
问题是该函数返回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是否属于A类。
我该如何解决这个问题?
感谢?
答案 0 :(得分:4)
您的代码调用未定义的行为,以便将无符号整数打印为带符号。
要打印stdint.h
类型,请参阅inttypes.h
。使用PRIu32
宏打印uint32_t
:
uint32_t u = 42;
printf("Value: %" PRIu32 "\n", u);
如果%u
不是uint32_t
,则无法保证标准typedef unsigned int uint32_t;
转换类型指标不正确。例如,对于32位long
和int
,可以typedef
为unsigned
。
对于十六进制,请使用PRIx32
或PRIX32
。
宏将映射到字符串文字,其中包含适合您平台的转换说明符,可以是"u"
。请注意,必须在前提部分中给出%
。连接相邻字符串文字的标准C功能将生成最终的格式字符串。没有运行时开销。
答案 1 :(得分:3)
唯一不对的是你的格式字符串。由于这些是无符号数字,因此您应该使用%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);
答案 2 :(得分:3)
正如其他人所提到的,%d
格式说明符用于打印已签名的int
。您传递的值是未签名的。使用错误的格式说明符会调用undefined behavior。
您需要使用%u
格式说明符将值打印为unsigned。
更好的是,使用%x
格式说明符将值打印为无符号十六进制。这样,每对十六进制字符对应于IP地址的一个字节,使其更易于阅读。
编辑:
但是,C标准并不保证int
至少为32位。您需要使用PRIu32
或PRIx32
宏来获取uint32_t
的正确格式说明符:
printf("%" PRIx32 "\n", integer_ip);
答案 3 :(得分:1)
htonl
返回32位无符号整数。
用于打印值的格式说明符%d
适用于签名整数值。
使用适合数据类型(%u
)的格式说明符,值将显示为正无符号数。