先说一下环境:
1.windows 7 32bit ,vs2005
问题的现象:
是一个关于两个ip计算是否是同一个网段的问题,ip和掩码均使用字符串保存的32位无符号整型,在计算的时候使用atoi转换成整型,然后使用&与运算计算两个ip是否在同一网段,但是却将同一网段的两个ip计算成两个不同网段的ip,详细见代码:
#include #include int main() { unsigned int src = 1280134664 ; //0x4C4D4E08; unsigned int dest = 1280134664 ; //0x4C4D4E11; unsigned int mask = 1280134664 ; //0xFFFFFF00; const char* szSrc = "1280134664"; //0x4C4D4E08 const char* szDest = "1280134673"; //0x4C4D4E11 const char* szMask = "4294967040"; //0xFFFFFF00 printf("the result is %d\n", (src & mask) == (dest & mask)); //数值运算 printf("ths string result is %d\n", (atoi(szSrc) & atoi(szMask)) == (atoi(szDest) & atoi(szMask))); //字符串运算 return 0; } |
结果如图:
OK,造成这个结果的原因是什么呢?看一下msdn对此函数的返回值的解释:
Each function returns the int value produced by interpreting the input characters as a number. The return value is 0 for atoi and _wtoi, if the input cannot be converted to a value of that type.
In the case of overflow with large negative integral values, LONG_MIN is returned. atoi and _wtoi return INT_MAX and INT_MIN on these conditions. In all out-of-range cases, errno is set to ERANGE. If the parameter passed in is NULL, the invalid parameter handler is invoked, as described in Parameter Validation. If execution is allowed to continue, these functions set errno to EINVAL and return 0.
通过msdn看到atoi在超过最大正整数的时候会返回INT_MAX 在32位环境下, INT_MAX的定义为:
#define INT_MAX 2147483647
所以他并不会按照字符串的字面值的大小自动翻转符号,所以mask的实际的返回值是2147483647,结果相当于:0X7FFFFFFF,所以两个IP计算出来会出现不在一个网段的情况
解决方法:
在需要将一个字符串转换到unsigned int 类型的时候,使用_atoi64()函数,64位足够包含unsigned int,修改之后的代码如下:
#include #include int main() { unsigned int src = 1280134664 ; //0x4C4D4E08; unsigned int dest = 1280134664 ; //0x4C4D4E11; unsigned int mask = 1280134664 ; //0xFFFFFF00; const char* szSrc = "1280134664"; //0x4C4D4E08 const char* szDest = "1280134673"; //0x4C4D4E11 const char* szMask = "4294967040"; //0xFFFFFF00 printf("the result is %d\n", (src & mask) == (dest & mask)); //数值运算 printf("ths string result is %d\n", (_atoi64(szSrc) & _atoi64(szMask)) == (_atoi64(szDest) & _atoi64(szMask))); //字符串运算 return 0; } |
运行结果如图:
总结:
这个坑属于主观想当然型的坑,一定注意确保自己使用的每一个函数都至少仔细地看过一次说明文档。