【发布时间】:2012-12-26 14:08:10
【问题描述】:
我正在查看strlen for glibc 的来源。他们使用magic bits 来查找字符串的长度。有人可以解释它是如何工作的。
谢谢
【问题讨论】:
我正在查看strlen for glibc 的来源。他们使用magic bits 来查找字符串的长度。有人可以解释它是如何工作的。
谢谢
【问题讨论】:
假设这个函数正在查看一个字符串——一次 4 个字节,正如 cmets 所解释的(我们假设 long ints 是 4 个字节)——当前的“块”看起来像这样:
'\3' '\3' '\0' '\3'
00000011 00000011 00000000 00000011 (as a string: "\x03\x03\x00\x03")
strlen 函数只是在这个字符串中寻找第一个零字节。它首先通过首先检查此magic_bits 快捷方式来确定每个 4 字节块中是否有 any 零字节:它将 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
^ ^ ^ ^
(孔位由^标记。)
而且,来自 cmets:
/* 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 计算。
【讨论】:
The one misfire occurs when bits 24-30 are clear and bit 31 is set;你能解释一下什么是失火吗?
我们的想法是一次将一个字节与零进行比较,而不是在其字节之一为零时一次检查一个unsigned long 对象。这意味着在sizeof (unsigned long) 为8 时检查8 字节。
使用位黑客,有一个快速已知的表达式可以确定一个字节是否等于零。然后,如果其中一个字节为零,则单独测试对象的字节以找到第一个为零的字节。使用按位运算的好处是减少了分支指令的数量。
在著名的斯坦福 Bit Twiddling Hacks 页面中解释了用于检查多字节对象的一个字节是否等于 0 的 bit hack 表达式,在
判断一个单词是否有零字节 http://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord