高效的strlen函数
来源:互联网 发布:2016詹姆斯数据统计 编辑:程序博客网 时间:2024/05/23 10:33
一般来说,一个入门的程序员大概可以不费劲的写出这样的 strlen 代码。
size_t my_strlen(const char * str) {<span style="white-space:pre"></span>size_t length = 0 ;<span style="white-space:pre"></span>while (*str++ )<span style="white-space:pre"></span>++ length;<span style="white-space:pre"></span>return length;}
#include <string.h>#include <stdlib.h>
<pre name="code" class="cpp">size_t strlen(const char *str) { const char *char_ptr; const unsigned long int *longword_ptr; unsigned long int longword, himagic, lomagic; /* Handle the first few characters by reading one character at a time. Do this until CHAR_PTR is aligned on a longword boundary. */ for (char_ptr = str; ((unsigned long int) char_ptr & (sizeof (longword) - 1)) != 0; ++char_ptr) if (*char_ptr == '\0') return char_ptr - str; /* All these elucidatory comments refer to 4-byte longwords, but the theory applies equally well to 8-byte longwords. */ longword_ptr = (unsigned long int *) char_ptr; /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits the "holes." Note that there is a hole just to the left of each byte, with an extra at the end: bits: 01111110 11111110 11111110 11111111 bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD The 1-bits make sure that carries propagate to the next 0-bit. The 0-bits provide holes for carries to fall into. */ himagic = 0x80808080L; lomagic = 0x01010101L; if (sizeof (longword) > 4) { /* 64-bit version of the magic. */ /* Do the shift in two steps to avoid a warning if long has 32 bits. */ himagic = ((himagic << 16) << 16) | himagic; lomagic = ((lomagic << 16) << 16) | lomagic; } if (sizeof (longword) > 8) abort(); /* Instead of the traditional loop which tests each character, we will test a longword at a time. The tricky part is testing if *any of the four* bytes in the longword in question are zero. */ for (;;) { longword = *longword_ptr++; if (((longword - lomagic) & ~longword & himagic) != 0) { /* Which of the bytes was the zero? If none of them were, it was a misfire; continue the search. */ const char *cp = (const char *) (longword_ptr - 1); if (cp[0] == 0) return cp - str; if (cp[1] == 0) return cp - str + 1; if (cp[2] == 0) return cp - str + 2; if (cp[3] == 0) return cp - str + 3; if (sizeof (longword) > 4) { if (cp[4] == 0) return cp - str + 4; if (cp[5] == 0) return cp - str + 5; if (cp[6] == 0) return cp - str + 6; if (cp[7] == 0) return cp - str + 7; } } }}
很明显这段代码比我们自己写的版本要复杂多了。其中注释写的比较清楚,我也不翻译了。
下面主要对其中几个点做分析吧。如果要看更详细的,请点击《strlen源码剖析》
简单版本和glibc版本主要的区别在于:通过内存对齐,来加快CPU的读取速度。
(在计算机在读取内存中的数据的时候,在内存对齐的状态下一次读取一个word的数据,是最节省时间的。例如在32位的计算机中,一个WORD为4 byte,则WORD数据的起始地址能被4整除的时候CPU的存取效率比较高。)
其中用到了两个技巧:
(1)由于传进来的字符串的地址有可能不是4字节(long int)对其的,因此首先找到4字节对其的那个地址
(2)技巧就是如何高效的判断在读取的4个字节中是否有字节为0
因此这个算法的整体思路如下:
(1)从字符串的开头开始,一次判断一个字符直到内存对齐(也就是地址能被4整除)。
(2)如果在内存对齐之前,字符串就已经结束了(也就是读取到'\0'),那么就return,否则到继续下一步;
(3)一次读入并判断一个DWORD,如果此DWORD中没有为0的字节,则继续下一个DWORD;如果判断出有'\0',就跳到下一步。
(4)找出该DWORD中第一个为0的字节的位置,然后return。
IT从业人员需要及时关注技术动态,但是互联网的内容却过于离散,好东西往往隐藏得很深。现在可以在微信公众号里面
搜索关注“小鱼儿的IT技术分享”,订阅我为大家每天汇总的IT技术信息。欢迎大家关注!
有兴趣的请点击《与IT技术相关的微信公众号》
0 0
- 高效的strlen函数
- strlen 的高效实现,充分利用位运算
- strlen函数的实现
- strlen函数的实现
- strlen()函数的实现
- strlen函数的实现
- strlen函数的实现
- 函数strlen()的实现
- strlen函数的实现
- strlen 函数的编写
- strlen函数的应用
- strlen函数的实现
- C++ strlen()函数的实现
- strlen函数的反汇编
- strlen函数的模拟实现
- strlen为何如此高效
- strlen高效实现
- strlen高效实现
- KVO示例
- HDU 4815 Little Tiger vs. Deep Monkey 01背包
- IOS 代码规范
- IOS 单列标准创建方案
- 高效的strcpy函数
- 高效的strlen函数
- 在UITableView中iOS UITableViewDelegate UITableViewDataSource执行顺序
- 各种initcall的执行先后顺序(module_init、postcore_initcall、arch_initcall、subsys_initcall、 fs_initcall)
- 二维数组旋转
- 苹果审核24项(中文版)
- iOS:KVO的概述与使用
- Ubuntu14.04 找不到ia32-lib 解决方案
- 易语言光速网络引擎教程第一课
- DP Leetcode - Maximum Product Subarray