如何确定单词中的字节是否为空

时间:2014-12-05 18:14:28

标签: c strlen magic-numbers

我正在从glibc读取“strlen”源代码,开发人员发现加速它的技巧是读取n个字节,其中n是长字的大小,而不是每次迭代读取1个字节。 / p>

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

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

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

其中longword是数据块,himagiclowmagic是神奇的定义为:

himagic = 0x80808080L;
lomagic = 0x01010101L;

以下是thoses值的评论

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

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

1 个答案:

答案 0 :(得分:4)

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

  

子表达式(v - 0x01010101UL),计算为高位设置   任何字节,只要v中的相应字节为零或大于   0x80。子表达式~v & 0x80808080UL求值为高位集   以字节为单位,其中v的字节没有设置其高位(所以   byte小于0x80)。最后,通过ANDing这两个子表达式   结果是高位设置,其中v中的字节为零,因为   由于第一个中的值大于0x80而设置的高位   子表达式被第二个掩盖。

glibc来源中的评论似乎令人困惑,因为它不再适用于代码实际正在做的事情 - 它描述了什么是实现Anderson在描述hasless(v, 1)算法之前描述的算法。