【发布时间】:2015-02-03 23:52:16
【问题描述】:
我正在从 glibc 中读取“strlen”源代码,开发人员发现加速它的技巧是读取 n 个字节,其中 n 是长字的大小,而不是在每次迭代时读取 1 个字节。
我假设一个长字有 4 个字节。
棘手的部分是函数读取的每个 4 字节的“块”都可以包含一个空字节,因此在每次迭代时,函数必须检查块中是否有空字节。他们喜欢这样做
if (((longword - lomagic) & ~longword & himagic) != 0) { /* null byte found */ }
其中longword 是数据块,himagic 和lowmagic 是定义为的神奇值:
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. */
这种查找空字节的技巧是如何工作的?
【问题讨论】:
-
@WeatherVane 我不认为你理解这个问题。关键是一次测试 8 个字节的字符串可能会加快操作速度。但是,如果 OP 不包含他自己的损坏代码,那就不会那么混乱了。 OP:请纯粹根据您显然引用的 32 位版本重写您的问题。此外,必须有一些代码来确定字中的哪个字节是零字节。
-
所以这个问题是智力问题?
-
@WeatherVane 有点。 ;-)
-
是的,这个问题与知识有关。另外,我没有包括我的“自己的损坏代码”(原始代码:github.com/lattera/glibc/blob/master/string/strlen.c)。无论如何,如果你愿意,我会让代码纯 32 位
标签: c strlen magic-numbers