您的位置:首页 > 其它

C库函数atoi的实现和一些讨论

2009-08-26 14:22 218 查看
函数原型:int atoi(const char* str)

函数功能:将字符串转换为对应的整数值

基本步骤:

1)处理空白字符;

2)处理符号字符;

3)处理数值字符;

4)返回结果。

函数实现:

]#include <stdio.h>
#include <assert.h>
static int atoi(const char* str)
{
int result = 0;
int sign = 0;
assert(str != NULL);
// proc whitespace characters
while (*str==' ' || *str=='/t' || *str=='/n')
++str;
// proc sign character
if (*str=='-')
{
sign = 1;
++str;
}
else if (*str=='+')
{
++str;
}
// proc numbers
while (*str>='0' && *str<='9')
{
result = result*10 + *str - '0';
++str;
}
// return result
if (sign)
result *= -1;
return result;
}


函数看上去没有什么问题,实际上也的确没什么问题。


是有的人可能会有疑问了,认为函数可能有个小小的bug。大家都知道,对于一个32位系统,int的典型范围为-2^31~2^31-1,那对于最小的这
个负数-2^31,其字符串为“-2147483648”,由于上面的函数实现在处理上将符号与数值分开来,这就造成了result的值必然会溢出,即
int类型并不能表示最小负数的绝对值2147483648。

但是幸运的是2147483648被int类型解释为-2147483648,二者的二进制补码编码都为1000 0000 0000 0000
0000 0000 0000 0000,这样result再乘以-1(二进制补码编码为1111 1111 1111 1111 1111 1111
1111 1111),截断后result的结果依然为1000 0000 0000 0000 0000 0000 0000
0000。

所以,对于最小的整数上面这个atoi的实现的结果是多少呢?答案为-2147483648,结果正确。

其实程序在运算的过程中并不会管数据的类型是什么,系统只是将数据编码为二进制进行运算,再将运算的结果用类型来解释。我想这也就是为什么大家
在glibc的源码中类似函数也没有看到关于越界处理内容的原因吧。

我们不得不感叹前人设计二进制反码表示法的精妙。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: