我正在浏览strlen for glibc的来源。他们使用magic bits
来查找字符串的长度。有人可以解释它是如何工作的。
谢谢
答案 0 :(得分:2)
相反,想法是将一个字节一次与零进行比较,而不是一次检查一个unsigned long
对象,如果其中一个字节为零。这意味着在8
为sizeof (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计算,然后将搜索范围缩小到单字节比较。