【问题标题】:How to determine if a byte is null in a word如何确定一个字节是否在一个单词中为空
【发布时间】:2015-02-03 23:52:16
【问题描述】:

我正在从 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.  */

这种查找空字节的技巧是如何工作的?

【问题讨论】:

  • @WeatherVane 我不认为你理解这个问题。关键是一次测试 8 个字节的字符串可能会加快操作速度。但是,如果 OP 不包含他自己的损坏代码,那就不会那么混乱了。 OP:请纯粹根据您显然引用的 32 位版本重写您的问题。此外,必须有一些代码来确定字中的哪个字节是零字节。
  • 所以这个问题是智力问题?
  • @WeatherVane 有点。 ;-)
  • 是的,这个问题与知识有关。另外,我没有包括我的“自己的损坏代码”(原始代码:github.com/lattera/glibc/blob/master/string/strlen.c)。无论如何,如果你愿意,我会让代码纯 32 位

标签: c strlen magic-numbers


【解决方案1】:

来自著名的"Bit Twiddling Hacks" page,作者 Sean Eron Anderson,描述了您所指的glibc 实现中当前使用的内容(安德森称算法为hasless(v, 1)):

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

glibc 源中的注释似乎令人困惑,因为它不再适用于代码实际执行的操作 - 它描述的是 Anderson 之前描述的算法的实现描述了hasless(v, 1) 算法。

【讨论】:

  • 有趣的是,代码中的另一条注释说,即使没有零字节,条件也可能为真。 /* Which of the bytes was the zero? If none of them were, it was a misfire; continue the search. */
  • 有趣!感谢您的信息。
  • 嗯,是的,这很有趣,但是当您找到一个字符串终止符然后需要拆分 4 或 8 字节 int、重新组织并继续时,您需要权衡开销。多年来,我尝试了 各种 技术,这些技术应该可以加快 其他 事情的速度,但如果你能找到它们通常是不值得的另一种解决瓶颈的方法,当我为我的继任者正确记录所有这些以便代码可读和可维护时,处理器速度已经翻了一番;-)
猜你喜欢
  • 1970-01-01
  • 2012-10-17
  • 2015-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-03
  • 1970-01-01
  • 2013-02-04
相关资源
最近更新 更多