神奇的位如何改善glibc中的strlen函数

时间:2012-12-26 14:08:11

标签: c glibc strlen

我正在浏览strlen for glibc的来源。他们使用magic bits来查找字符串的长度。有人可以解释它是如何工作的。 谢谢

2 个答案:

答案 0 :(得分:2)

相反,想法是将一个字节一次与零进行比较,而不是一次检查一个unsigned long对象,如果其中一个字节为零。这意味着在8sizeof (unsigned long)的时候检查8个字节。

使用bit hacks,有一个快速已知的表达式可以确定其中一个字节是否等于零。然后,如果其中一个字节等于零,则单独测试对象的字节以找到第一个为零的字节。使用按位运算的优点是减少了分支指令的数量。

用于检查多字节对象的一个​​字节是否等于零的位破解表达式在着名的Stanford Bit Twiddling Hacks页面中进行了解释,

  

确定单词是否具有零字节   http://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord

答案 1 :(得分:2)

假设这个函数正在查找一个字符串 - 一次4个字节,正如注释所解释的那样(我们假设long ints是4个字节) - 并且当前的“chunk”看起来像这样: / p>

'\3'     '\3'     '\0'     '\3'
00000011 00000011 00000000 00000011  (as a string: "\x03\x03\x00\x03")

strlen函数只是查找此字符串中的第一个零字节。它首先通过首先检查此magic_bits快捷方式,为每个4字节块确定其中是否有任何零字节:它将4个字节添加到此值:

01111110 11111110 11111110 11111111

通过传播进位,将任何非零字节添加到此值将导致1溢出到由零标记的孔中。对于我们的块,它看起来像这样:

  11111111 111111          1 1111111   Carries
  00000011 00000011 00000000 00000011  Chunk
  01111110 11111110 11111110 11111111  Magic bits
+ -----------------------------------
  10000010 00000001 11111111 00000010
  ^      ^        ^        ^         

(孔位用^标记。)

并且,从评论:

       /* Look at only the hole bits.  If any of the hole bits
          are unchanged, most likely one of the bytes was a
          zero.  */

如果块中没有零,则所有的孔位都将设置为1。但是,由于零字节,一个孔位没有被传播进位填充,然后我们可以检查它是哪个字节。

本质上,它通过将一些位加法魔法应用于4字节块以扫描零来加速strlen计算,然后将搜索范围缩小到单字节比较。