atoi atol实现

看了atol的实现,发现char到int的转换比较奇怪:c = (int)(unsigned char)*nptr++; 先将char转为unsigned再转为int,于是测试了下,发现有如下结果:
void main()
{
    char c = 0x80;
    unsigned uc = 0x80;
    printf("c2i=%x,c2ui=%x,uc2i=%x,uc2ui=%x\n", \
    (int)c,(unsigned int)c,(int)uc,(unsigned int)uc
    );
}
结果:
c2i=ffffff80,c2ui=ffffff80,uc2i=80,uc2ui=80

可以发现,如果char默认为signed(可能是平台相关的),则将char转为int或uint时,会有符号位扩展,而unsigned char则不会。atol/atoi函数应该希望避免符号位扩展而带来问题。不过,好在数字0到9的ACSII码并没有超过0x7F,因此是否事先转成unsigned char应该不会对结果有影响。

另,转一篇类似问题造成的BUG:http://testing.etao.com/node/217


另外,atoi/atol是笔试面试常考问题,虽然看似不难,但往往实现起来漏洞百出。实现时注意以下几点:
1. 跳过开头空格。
2. 判断第一个有效字符(非空格)是否是符号‘+’或‘-’。
3. 当遇到非数字时,函数结束,输出之前字串代表的整数。
4. 为严谨起见,就是文中提到的的char转int问题。


附atol源码:
[cpp] view plain copy print ?
  1. long __cdecl atol(  
  2.         const char *nptr  
  3.         )  
  4. {  
  5.         int c;              /* current char */  
  6.         long total;         /* current total */  
  7.         int sign;           /* if '-', then negative, otherwise positive */  
  8.   
  9.         /* skip whitespace */  
  10.         while ( isspace((int)(unsigned char)*nptr) )  
  11.             ++nptr;  
  12.   
  13.         c = (int)(unsigned char)*nptr++;  
  14.         sign = c;           /* save sign indication */  
  15.         if (c == '-' || c == '+')  
  16.             c = (int)(unsigned char)*nptr++;    /* skip sign */  
  17.   
  18.         total = 0;  
  19.   
  20.         while (isdigit(c)) {  
  21.             total = 10 * total + (c - '0');     /* accumulate digit */  
  22.             c = (int)(unsigned char)*nptr++;    /* get next char */  
  23.         }  
  24.   
  25.         if (sign == '-')  
  26.             return -total;  
  27.         else  
  28.             return total;   /* return result, negated if necessary */  
  29. }  
int atoi(const char *nptr)
{
return (int)atol(nptr);
}


你可能感兴趣的:(atoi,atol)