strlen 的高效实现,充分利用位运算
来源:互联网 发布:淘宝男装潮牌店铺排行 编辑:程序博客网 时间:2024/05/11 12:47
处理字符串的时候,经常需要获得字符串的长度,C标准库提供了strlen这个函数,
实现一个普通的版本并不困难,大致上跟下面的代码类似。
挨个判断字符是否为0,遇到0则退出,代码很简洁,也不算性能低。只是有点不足,
在字长是4字节或者8字节的计算机上,每次只读取一个字节,有些浪费计算机的能力,
如果每次都读取4字节或者8字节,总的读取次数就大大减少,在读取4字节或者8字节
的时候,如果地址不在边界上,机器就要分两次才能读取完成,这样性能将会降低,
弱化优化效果,所以前几个字符必须单独处理,然后从字长边界地址开始,每次读取
4字节或者8字节。
新的方式:
- 开头的几字节单独处理
- 中间部分以4字节或8字节为单位处理
- 最后几字节单独处理
看上去很好,但是还有一个问题,4字节或者8字节读取的时候,如何保证有全0的字节
存在,因为0是用来表示字符串的结尾的。判断连续的几个字节中是否存在全0的字节,
成了优化的关键。我们不能一个字节一个字节判断,因为优化的思想就是一次读取多个
字节,减少总的读取次数,单独判断每一个字节的话,就失去优化的效果了。
怎么办呢,当然首先考虑位运算了。
- 一个纯0的字节有什么特点? 很明显,每一位都是0,按位取反后每一位都是1。
- 一个全0的字节还有什么特点? 这个字节减1,必然要从更高字节借1,借1后,
该字节的最高位必然是1。
似乎有些眉目了,以4字节整数n为例,我们只要把每个字节分别减去1,如果有纯0
的字节存在,必然会有借位,借位之后会在字节最高 位留下一个1。只要判断每个
字节的最高位是否存在1就可以了,然而,这里还有一个问题,就是这个4字节整数
里,某些字节本来最高 位可能就含有1,所以必须排除掉这些字节。
解决方案:
- 将n的每字节分别减1,再取每字节最高位,得x,借位的字节最高位一定是1
- 将n的每字节按位取反后取最高位,得y,n中最高位是0的字节,在y中该位是1
- 将x和y按位与运算,若不为0,则n存在某字节最高位不是1,但在借位时变1了
若n中存在全0字节,则 x&y 一定不为0,因为借位的那个字节最高位会被置为1;
若n中不存在全0字节,则不会产生借位,x&y 等于0。写出公式如下:
x&y == (n-0x01010101) & ~n & 0x80808080
如果是标准ASCII字符,每字节最高位一定是0,此时只考虑借位即可,不必考虑原本
最高位就是1的情况,用 x&y == (n-0x01010101) & 0x8080808 就可以了。
以下是glibc中strcat的实现,基于以上结论,就不难理解了。
注意:glibc还考虑了字长是8字节的情况。
- strlen 的高效实现,充分利用位运算
- 高效的位运算
- strlen高效实现
- strlen高效实现
- strlen高效实现
- 高效的strlen函数
- 运算的位实现
- 小笔记-用位运算实现求平均数的一个较高效方法
- %的位运算实现方式
- 高效面试之位运算
- C++细节学习之高效的位运算
- C++ 位运算:怎样使用位运算简洁高效的完成计算
- 位运算---只使用位运算实现整数的加减乘除
- 高效开发:充分利用ASP.NET 2.0 的新特性
- 基本操作的位运算实现
- 关于位运算符实现的问题
- 用位运算实现 | 与 ^ 的功能
- 位运算实现两个数的加法
- One Month, In us
- 在自己的程序中显示网页
- 钢琴弹到肖邦的曲子就根本无视10级了.
- VS2008 Express 编译安装 QT4.5.3
- 屏蔽在线视频中的广告 优酷,土豆
- strlen 的高效实现,充分利用位运算
- 关于跳舞毯按键映射的构想
- 爆炸!殷桃东方快乐童装首次承认自己确实被包养但不是骗人的文强而是成龙
- hpux+slvm+mc/sg+oracle 10g rac实施手册
- 软考中有关死锁的问题
- WinterBoard中Info.plist的设置-翻译
- 《Sybex Oracle 10g 新特性学习笔记》——安全性和SQL功能增强[2]
- 如何用C#获得文件信息以及扩展信息
- oracle10g for HP-UX PA-RISC安装