isdigit()极品实现

    我不得不承认,在编程的世界,无奇不有,码农的创造力是无穷的,也是妙不可言的!只要涉及到效率,永远是没有最快,只有更快!

    我们知道,在标准C中,有函数int isdigit(int c)可以用来判断字符c是否为0~9之间的数字。比如:

1 int a = isdigit('1');    //a == 1
2 int b = isdigit('a');    //b == 0
3 int c = isdigit(3);      //c == 0

    知道了isdigit的用途,我们可以抛出问题了:  你会怎样实现isdigit(int c)呢?

    我想,绝大多数人的第一反应和最终想法都是使用宏定义去实现这个简单的函数,如下所示:

1 #define isdigit(c) ((c) >= '0' && (c) <= '9')

    简洁又美观,使用宏连函数调用的开销都省掉了,效率也不差,这就是最完美的了吗?让我们看看linux内核中是怎样实现这个函数的:

01 #define _U      0x01    /* upper */
02 #define _L      0x02    /* lower */
03 #define _D      0x04    /* digit */
04 #define _C      0x08    /* cntrl */
05 #define _P      0x10    /* punct */
06 #define _S      0x20    /* white space (space/lf/tab) */
07 #define _X      0x40    /* hex digit */
08 #define _SP     0x80    /* hard space (0x20) */
09   
10 extern unsigned char _ctype[];
11  
12 #define isdigit(c) ((_ctype+1)[c]&(_D))
13  
14 unsigned char _ctype[] = {0x00,                 /* EOF */
15  _C,_C,_C,_C,_C,_C,_C,_C,                        /* 0-7 */
16  _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C,         /* 8-15 */
17  _C,_C,_C,_C,_C,_C,_C,_C,                        /* 16-23 */
18  _C,_C,_C,_C,_C,_C,_C,_C,                        /* 24-31 */
19  _S|_SP,_P,_P,_P,_P,_P,_P,_P,                    /* 32-39 */
20  _P,_P,_P,_P,_P,_P,_P,_P,                        /* 40-47 */
21  _D,_D,_D,_D,_D,_D,_D,_D,                        /* 48-55 */
22  _D,_D,_P,_P,_P,_P,_P,_P,                        /* 56-63 */
23  _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U,      /* 64-71 */
24  _U,_U,_U,_U,_U,_U,_U,_U,                        /* 72-79 */
25  _U,_U,_U,_U,_U,_U,_U,_U,                        /* 80-87 */
26  _U,_U,_U,_P,_P,_P,_P,_P,                        /* 88-95 */
27  _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L,      /* 96-103 */
28  _L,_L,_L,_L,_L,_L,_L,_L,                        /* 104-111 */
29  _L,_L,_L,_L,_L,_L,_L,_L,                        /* 112-119 */
30  _L,_L,_L,_P,_P,_P,_P,_C,                        /* 120-127 */
31  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,                /* 128-143 */
32  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,                /* 144-159 */
33  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,                /* 160-175 */
34  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,                /* 176-191 */
35  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,                /* 192-207 */
36  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,                /* 208-223 */
37  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,                /* 224-239 */
38  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};               /* 240-255 */

    很神奇吧,典型的空间换时间的做法。在这里进行简单的解释:我们知道字符'0'~'9'对应的ASCII码为48~57,映射到上面的_ctype数组相应的位置全是_D,_D&_D为真,因此可以对'0'~'9'进行正确的判断。剩下的就是要对此范围外的字符判断为false就OK了。这里的做法精华之处也就在于此,对不同种类的字符进行了分类,并使用唯一的二进制来进行标识,使用&和|保证了不同类别的字符不会同时满足两种分类的条件。

    文末说一句,有时间多看看linux内核的代码,毕竟都是经过千锤百炼的。也许很多代码诡异的让你头大,但是hack出其思想后,获得的喜悦也是无法言表的。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值