简体   繁体   English

将IP地址从char *转换为uin32_t

[英]Converting IP addresses from char * to uin32_t

I was inspired by Conversion of IP address to integer 我的灵感来自IP地址到整数的转换

My code looks like this: 我的代码如下所示:

    uint32_r parseIPV4string(char * ipAddress){
    char ipbytes[4];
    sscanf(ipAddress, "%uhh.%uhh.%uhh.%uhh", &ipbytes[3], &ipbytes[2], &ipbytes[1], &ipbytes[0]);
    return ipbytes[0] | ipbytes[1] << 8 | ipbytes[2] << 16 | ipbytes[3] << 24;
}

Virtually an exact copy, my problem is however, that my ip addresses aren't coming out properly. 实际上,实际上是一个精确的副本,但是我的问题是我的IP地址无法正确显示。 I am watching in shock and awe as "129.173.118.0" and "129.173.31.187" both return 2164260864 我震惊和敬畏地看着“ 129.173.118.0”和“ 129.173.31.187”都返回2164260864

Can someone explain what is going on? 有人可以解释发生了什么吗?

Perhaps I am using the parser incorrectly, I am unsure exactly how it works, namely the "%uhh." 也许我使用的解析器不正确,我不确定它的工作原理,即“%uhh”。 are new to me and I have no idea as to whatever is going on in that return statement. 对我来说是新手,我不知道该return语句中发生了什么。

Your sscanf is failing. 您的sscanf失败。 When this happens, it leaves the arguments in an indeterminate state. 发生这种情况时,参数将处于不确定状态。 So your return statement returns garbage. 因此,您的return语句返回垃圾。

%uhh means to read into an unsigned int , and then match the letter 'h' twice. %uhh表示读入unsigned int ,然后将字母'h'匹配两次。 If your input string did not actually contain h after the first number, then matching fails and sscanf will return 1 (or 0 if there wasn't even a first number). 如果您输入的字符串实际上没有在第一个数字之后包含h ,则匹配失败,并且sscanf将返回1 (如果没有第一个数字,则返回0 )。

You probably meant %hhu , to read an integer and store in an unsigned char , however you also need to make ipbytes be unsigned char to match the format specifier. 您可能是说%hhu ,以读取整数并存储在unsigned char ,但是您还需要使ipbytesunsigned char以匹配格式说明符。 The specifier for plain or signed char is %hhd . 纯字符或带符号char的说明符为%hhd

This array should be unsigned anyway, otherwise your | 这个数组应该是无符号的,无论如何,否则你| later on is going to mess up (remember that negative numbers have a lot of 1 bits set, in 2's complement). 稍后会搞砸(请记住,负数设置了很多1位,以2的补码表示)。

A further problem is that if your system has 32-bit int, then even when using unsigned char , the expression ipbytes[3] << 24 causes undefined behaviour if the high bit of ipbytes[3] is set, due to signed integer overflow: the integer promotions unfortunately promote unsigned char to a signed int . 进一步的问题是,如果您的系统中使用,即使有32位int,然后unsigned char ,所述表达ipbytes[3] << 24原因如果满足高比特未定义行为ipbytes[3]符号整数溢出被设置时,由于:不幸的是, 整数提升将 unsigned char提升为一个有符号的int

Finally, if the system has 16-bit int then the << 16 and << 24 fail entirely. 最后,如果系统具有16位int,则<< 16<< 24完全失败。

A robust way to write the function would be to avoid any undesirable promotions: 编写该函数的一种可靠方法是避免出现任何不良提升:

uint32_t parseIPV4string(char const * ipAddress)
{
    unsigned int ip[4];

    if ( 4 != sscanf(ipAddress, "%u.%u.%u.%u", &ip[0], &ip[1], &ip[2], &ip[3]) )
         return 0;   // or some other indicator or error

    return ipbytes[3] + ipbytes[2] * 0x100 + ipbytes[1] * 0x10000ul + ipbytes[0] * 0x1000000ul;
}

If you really want to use | 如果您真的想使用| and << then you either have to use some ugly casts; <<那么或者使用一些丑陋的铸件; or change ip to have the type uint32_t in which case "%u" must be replaced by "%" SCNu32 . 或将ip更改为uint32_t类型,在这种情况下,必须将"%u"替换为"%" SCNu32

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM