atol的实现【转】

本文转载自:http://blog.csdn.net/cwqbuptcwqbupt/article/details/7518582

看了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
 
    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. }  
posted @ 2017-05-09 10:29  请给我倒杯茶  阅读(799)  评论(0编辑  收藏  举报