2014-12-05 59 views
0

我正在读取glibc中的“strlen”源代码,并且发现加速它的技巧开发人员是读取n个字节,其中n是长字的大小,而不是在每次迭代时读取1个字节。如何确定一个字中的字节是否为

我会假设一个长字有4个字节。

棘手的部分是函数读取的4个字节的每个“块”都可以包含一个空字节,因此在每次迭代中,函数都必须检查块中是否有空字节。他们不喜欢它

if (((longword - lomagic) & ~longword & himagic) != 0) { /* null byte found */ } 

其中longword是数据块和himagiclowmagic是神奇的价值观定义为:

himagic = 0x80808080L; 
lomagic = 0x01010101L; 

这里是放入系统值注释

/* 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. */ 

如何这是否找到空字节工作的技巧?

+0

评估'himagic'本身就可以让你感觉到任何地方?你指的是'strlen',所以它是你正在阅读的文本。为什么通过8字节的块读取文本?什么是空字节。 8位字节的值为0..255或-128..127。请发布一些适当的代码,让你接近你要去的地方。如果你真的想加快文件读取速度,你可以自己做一个'fread()'块来解析数组,或者使用'fgets()'并读取一整行文本。 – 2014-12-05 18:25:09

+0

@WeatherVane我不认为你理解这个问题。问题是,一次测试8个字节的字符串可能会加速操作。然而,如果OP没有包含他自己的破解代码,那么它就不那么令人困惑了。 OP:请纯粹根据您显然引用的32位版本重写您的问题。此外,必须有一些代码来确定该字中哪个*字节是零字节。 – ooga 2014-12-05 18:29:57

+0

所以这个问题是关于知识兴趣的? – 2014-12-05 18:34:44

回答

4

距离著名的"Bit Twiddling Hacks" page肖恩玉龙安德森,是什么在glibc实现你指的是当前使用说明(安德森调用算法hasless(v, 1)):

子表达式(v - 0x01010101UL),计算结果为当v中的相应字节为零或大于 0x80时,高位在 中设置的任何字节。子表达式~v & 0x80808080UL评估为以字节为单位的高位集 ,其中v的字节没有设置其高位(因此 字节小于0x80)。最后,通过对这两个子表达式进行“与”运算,结果是v中字节为零的高位集合,因为由于 子表达式中大于0x80的值而设置的高位被屏蔽掉第二。

看来,在glibc源的注释(S)是混乱,因为它并不适用于什么样的代码实际上做了 - 它描述什么将是该算法的实现,安德森描述只是在描述hasless(v, 1)算法之前。

+0

有趣的是,代码中的另一个评论说,即使没有零字节,条件也可能是真的。 '/ *哪个字节是零?如果他们都不是,那是一场失火;继续搜索。 * /' – ooga 2014-12-05 18:50:15

+1

@ooga - 评论已过时。查看我的答案更新。 – 2014-12-05 18:54:22

+0

有趣!谢谢(你的)信息。 – ooga 2014-12-05 18:58:03