这是一个与问题中提供的输出相匹配的函数(至少在有限的测试下)。它使用表格查找,表格是由一次性脚本生成的。老实说,我不确定它的性能是否与使用 bit testing hackery 或 GCC builtins 的建议相比具有竞争力,但我敢打赌它不会太远。
struct zeros {
unsigned char leading;
unsigned char internal;
unsigned char trailing;
};
// forward declaration so the long, non-interesting table is at the
// end of this
static struct zeros const zero_table[256];
int find_zero_bits_offset( char const* data, int datalen, int desired)
{
int offset = -1;
int found = 0;
char const* dataptr = &data[0];
char const* endptr = &data[datalen];
// first, find which byte the sequence of zeros begins
while (!found && (dataptr != endptr)) {
unsigned char ch1 = *dataptr++;
unsigned char ch2 = (dataptr != endptr) ? *dataptr : 0xff;
int internal = zero_table[ch1].internal;
int trailing = zero_table[ch1].trailing;
int leading = zero_table[ch2].leading;
found = (desired <= internal) ||
(trailing && (desired <= (trailing + leading)));
}
// now zero in on where the sequence starts within the byte
if (found) {
char ch = 0;
unsigned int mask = 0;
--dataptr;
// dataptr points to the byte where the sequence of zeros starts.
// figure out exactly where the sequence is...
// there's possibly some opportunity for optimization, if neccesary,
// by testing if the sequence was found in the "leading", "internal", or
// "trailing" cases. But the explicit loop will only iterate at most
// 8 times (and will early-out on the first iteration if the match is
// for the "leading" case) that it didn't seem too important
ch = *dataptr;
offset = (dataptr - data) * 8;
// figure out where the appropriate internal run starts
// note that the offset we need to return isn't necessarily the
// offset for the run of zeros counted by zero_table[tmp].internal_offset
// since a sufficient shorter run might come first
// there may be a more efficient bithack for this, but the
// loop will iterate at most 8 times...
mask = ((1 << desired) - 1);
mask <<= (8 - desired);
while ((ch & mask) != 0) {
++offset;
mask >>= 1;
}
}
else {
// however you want to handle the "not found" situation.
// This is equivalent to what was in the question:
offset = (endptr - data) * 8;
}
return offset;
}
static struct zeros const zero_table[256] = {
{ 8, 8, 8 }, // 0000 0000
{ 7, 7, 0 }, // 0000 0001
{ 6, 6, 1 }, // 0000 0010
{ 6, 6, 0 }, // 0000 0011
{ 5, 5, 2 }, // 0000 0100
{ 5, 5, 0 }, // 0000 0101
{ 5, 5, 1 }, // 0000 0110
{ 5, 5, 0 }, // 0000 0111
{ 4, 4, 3 }, // 0000 1000
{ 4, 4, 0 }, // 0000 1001
{ 4, 4, 1 }, // 0000 1010
{ 4, 4, 0 }, // 0000 1011
{ 4, 4, 2 }, // 0000 1100
{ 4, 4, 0 }, // 0000 1101
{ 4, 4, 1 }, // 0000 1110
{ 4, 4, 0 }, // 0000 1111
{ 3, 4, 4 }, // 0001 0000
{ 3, 3, 0 }, // 0001 0001
{ 3, 3, 1 }, // 0001 0010
{ 3, 3, 0 }, // 0001 0011
{ 3, 3, 2 }, // 0001 0100
{ 3, 3, 0 }, // 0001 0101
{ 3, 3, 1 }, // 0001 0110
{ 3, 3, 0 }, // 0001 0111
{ 3, 3, 3 }, // 0001 1000
{ 3, 3, 0 }, // 0001 1001
{ 3, 3, 1 }, // 0001 1010
{ 3, 3, 0 }, // 0001 1011
{ 3, 3, 2 }, // 0001 1100
{ 3, 3, 0 }, // 0001 1101
{ 3, 3, 1 }, // 0001 1110
{ 3, 3, 0 }, // 0001 1111
{ 2, 5, 5 }, // 0010 0000
{ 2, 4, 0 }, // 0010 0001
{ 2, 3, 1 }, // 0010 0010
{ 2, 3, 0 }, // 0010 0011
{ 2, 2, 2 }, // 0010 0100
{ 2, 2, 0 }, // 0010 0101
{ 2, 2, 1 }, // 0010 0110
{ 2, 2, 0 }, // 0010 0111
{ 2, 3, 3 }, // 0010 1000
{ 2, 2, 0 }, // 0010 1001
{ 2, 2, 1 }, // 0010 1010
{ 2, 2, 0 }, // 0010 1011
{ 2, 2, 2 }, // 0010 1100
{ 2, 2, 0 }, // 0010 1101
{ 2, 2, 1 }, // 0010 1110
{ 2, 2, 0 }, // 0010 1111
{ 2, 4, 4 }, // 0011 0000
{ 2, 3, 0 }, // 0011 0001
{ 2, 2, 1 }, // 0011 0010
{ 2, 2, 0 }, // 0011 0011
{ 2, 2, 2 }, // 0011 0100
{ 2, 2, 0 }, // 0011 0101
{ 2, 2, 1 }, // 0011 0110
{ 2, 2, 0 }, // 0011 0111
{ 2, 3, 3 }, // 0011 1000
{ 2, 2, 0 }, // 0011 1001
{ 2, 2, 1 }, // 0011 1010
{ 2, 2, 0 }, // 0011 1011
{ 2, 2, 2 }, // 0011 1100
{ 2, 2, 0 }, // 0011 1101
{ 2, 2, 1 }, // 0011 1110
{ 2, 2, 0 }, // 0011 1111
{ 1, 6, 6 }, // 0100 0000
{ 1, 5, 0 }, // 0100 0001
{ 1, 4, 1 }, // 0100 0010
{ 1, 4, 0 }, // 0100 0011
{ 1, 3, 2 }, // 0100 0100
{ 1, 3, 0 }, // 0100 0101
{ 1, 3, 1 }, // 0100 0110
{ 1, 3, 0 }, // 0100 0111
{ 1, 3, 3 }, // 0100 1000
{ 1, 2, 0 }, // 0100 1001
{ 1, 2, 1 }, // 0100 1010
{ 1, 2, 0 }, // 0100 1011
{ 1, 2, 2 }, // 0100 1100
{ 1, 2, 0 }, // 0100 1101
{ 1, 2, 1 }, // 0100 1110
{ 1, 2, 0 }, // 0100 1111
{ 1, 4, 4 }, // 0101 0000
{ 1, 3, 0 }, // 0101 0001
{ 1, 2, 1 }, // 0101 0010
{ 1, 2, 0 }, // 0101 0011
{ 1, 2, 2 }, // 0101 0100
{ 1, 1, 0 }, // 0101 0101
{ 1, 1, 1 }, // 0101 0110
{ 1, 1, 0 }, // 0101 0111
{ 1, 3, 3 }, // 0101 1000
{ 1, 2, 0 }, // 0101 1001
{ 1, 1, 1 }, // 0101 1010
{ 1, 1, 0 }, // 0101 1011
{ 1, 2, 2 }, // 0101 1100
{ 1, 1, 0 }, // 0101 1101
{ 1, 1, 1 }, // 0101 1110
{ 1, 1, 0 }, // 0101 1111
{ 1, 5, 5 }, // 0110 0000
{ 1, 4, 0 }, // 0110 0001
{ 1, 3, 1 }, // 0110 0010
{ 1, 3, 0 }, // 0110 0011
{ 1, 2, 2 }, // 0110 0100
{ 1, 2, 0 }, // 0110 0101
{ 1, 2, 1 }, // 0110 0110
{ 1, 2, 0 }, // 0110 0111
{ 1, 3, 3 }, // 0110 1000
{ 1, 2, 0 }, // 0110 1001
{ 1, 1, 1 }, // 0110 1010
{ 1, 1, 0 }, // 0110 1011
{ 1, 2, 2 }, // 0110 1100
{ 1, 1, 0 }, // 0110 1101
{ 1, 1, 1 }, // 0110 1110
{ 1, 1, 0 }, // 0110 1111
{ 1, 4, 4 }, // 0111 0000
{ 1, 3, 0 }, // 0111 0001
{ 1, 2, 1 }, // 0111 0010
{ 1, 2, 0 }, // 0111 0011
{ 1, 2, 2 }, // 0111 0100
{ 1, 1, 0 }, // 0111 0101
{ 1, 1, 1 }, // 0111 0110
{ 1, 1, 0 }, // 0111 0111
{ 1, 3, 3 }, // 0111 1000
{ 1, 2, 0 }, // 0111 1001
{ 1, 1, 1 }, // 0111 1010
{ 1, 1, 0 }, // 0111 1011
{ 1, 2, 2 }, // 0111 1100
{ 1, 1, 0 }, // 0111 1101
{ 1, 1, 1 }, // 0111 1110
{ 1, 1, 0 }, // 0111 1111
{ 0, 7, 7 }, // 1000 0000
{ 0, 6, 0 }, // 1000 0001
{ 0, 5, 1 }, // 1000 0010
{ 0, 5, 0 }, // 1000 0011
{ 0, 4, 2 }, // 1000 0100
{ 0, 4, 0 }, // 1000 0101
{ 0, 4, 1 }, // 1000 0110
{ 0, 4, 0 }, // 1000 0111
{ 0, 3, 3 }, // 1000 1000
{ 0, 3, 0 }, // 1000 1001
{ 0, 3, 1 }, // 1000 1010
{ 0, 3, 0 }, // 1000 1011
{ 0, 3, 2 }, // 1000 1100
{ 0, 3, 0 }, // 1000 1101
{ 0, 3, 1 }, // 1000 1110
{ 0, 3, 0 }, // 1000 1111
{ 0, 4, 4 }, // 1001 0000
{ 0, 3, 0 }, // 1001 0001
{ 0, 2, 1 }, // 1001 0010
{ 0, 2, 0 }, // 1001 0011
{ 0, 2, 2 }, // 1001 0100
{ 0, 2, 0 }, // 1001 0101
{ 0, 2, 1 }, // 1001 0110
{ 0, 2, 0 }, // 1001 0111
{ 0, 3, 3 }, // 1001 1000
{ 0, 2, 0 }, // 1001 1001
{ 0, 2, 1 }, // 1001 1010
{ 0, 2, 0 }, // 1001 1011
{ 0, 2, 2 }, // 1001 1100
{ 0, 2, 0 }, // 1001 1101
{ 0, 2, 1 }, // 1001 1110
{ 0, 2, 0 }, // 1001 1111
{ 0, 5, 5 }, // 1010 0000
{ 0, 4, 0 }, // 1010 0001
{ 0, 3, 1 }, // 1010 0010
{ 0, 3, 0 }, // 1010 0011
{ 0, 2, 2 }, // 1010 0100
{ 0, 2, 0 }, // 1010 0101
{ 0, 2, 1 }, // 1010 0110
{ 0, 2, 0 }, // 1010 0111
{ 0, 3, 3 }, // 1010 1000
{ 0, 2, 0 }, // 1010 1001
{ 0, 1, 1 }, // 1010 1010
{ 0, 1, 0 }, // 1010 1011
{ 0, 2, 2 }, // 1010 1100
{ 0, 1, 0 }, // 1010 1101
{ 0, 1, 1 }, // 1010 1110
{ 0, 1, 0 }, // 1010 1111
{ 0, 4, 4 }, // 1011 0000
{ 0, 3, 0 }, // 1011 0001
{ 0, 2, 1 }, // 1011 0010
{ 0, 2, 0 }, // 1011 0011
{ 0, 2, 2 }, // 1011 0100
{ 0, 1, 0 }, // 1011 0101
{ 0, 1, 1 }, // 1011 0110
{ 0, 1, 0 }, // 1011 0111
{ 0, 3, 3 }, // 1011 1000
{ 0, 2, 0 }, // 1011 1001
{ 0, 1, 1 }, // 1011 1010
{ 0, 1, 0 }, // 1011 1011
{ 0, 2, 2 }, // 1011 1100
{ 0, 1, 0 }, // 1011 1101
{ 0, 1, 1 }, // 1011 1110
{ 0, 1, 0 }, // 1011 1111
{ 0, 6, 6 }, // 1100 0000
{ 0, 5, 0 }, // 1100 0001
{ 0, 4, 1 }, // 1100 0010
{ 0, 4, 0 }, // 1100 0011
{ 0, 3, 2 }, // 1100 0100
{ 0, 3, 0 }, // 1100 0101
{ 0, 3, 1 }, // 1100 0110
{ 0, 3, 0 }, // 1100 0111
{ 0, 3, 3 }, // 1100 1000
{ 0, 2, 0 }, // 1100 1001
{ 0, 2, 1 }, // 1100 1010
{ 0, 2, 0 }, // 1100 1011
{ 0, 2, 2 }, // 1100 1100
{ 0, 2, 0 }, // 1100 1101
{ 0, 2, 1 }, // 1100 1110
{ 0, 2, 0 }, // 1100 1111
{ 0, 4, 4 }, // 1101 0000
{ 0, 3, 0 }, // 1101 0001
{ 0, 2, 1 }, // 1101 0010
{ 0, 2, 0 }, // 1101 0011
{ 0, 2, 2 }, // 1101 0100
{ 0, 1, 0 }, // 1101 0101
{ 0, 1, 1 }, // 1101 0110
{ 0, 1, 0 }, // 1101 0111
{ 0, 3, 3 }, // 1101 1000
{ 0, 2, 0 }, // 1101 1001
{ 0, 1, 1 }, // 1101 1010
{ 0, 1, 0 }, // 1101 1011
{ 0, 2, 2 }, // 1101 1100
{ 0, 1, 0 }, // 1101 1101
{ 0, 1, 1 }, // 1101 1110
{ 0, 1, 0 }, // 1101 1111
{ 0, 5, 5 }, // 1110 0000
{ 0, 4, 0 }, // 1110 0001
{ 0, 3, 1 }, // 1110 0010
{ 0, 3, 0 }, // 1110 0011
{ 0, 2, 2 }, // 1110 0100
{ 0, 2, 0 }, // 1110 0101
{ 0, 2, 1 }, // 1110 0110
{ 0, 2, 0 }, // 1110 0111
{ 0, 3, 3 }, // 1110 1000
{ 0, 2, 0 }, // 1110 1001
{ 0, 1, 1 }, // 1110 1010
{ 0, 1, 0 }, // 1110 1011
{ 0, 2, 2 }, // 1110 1100
{ 0, 1, 0 }, // 1110 1101
{ 0, 1, 1 }, // 1110 1110
{ 0, 1, 0 }, // 1110 1111
{ 0, 4, 4 }, // 1111 0000
{ 0, 3, 0 }, // 1111 0001
{ 0, 2, 1 }, // 1111 0010
{ 0, 2, 0 }, // 1111 0011
{ 0, 2, 2 }, // 1111 0100
{ 0, 1, 0 }, // 1111 0101
{ 0, 1, 1 }, // 1111 0110
{ 0, 1, 0 }, // 1111 0111
{ 0, 3, 3 }, // 1111 1000
{ 0, 2, 0 }, // 1111 1001
{ 0, 1, 1 }, // 1111 1010
{ 0, 1, 0 }, // 1111 1011
{ 0, 2, 2 }, // 1111 1100
{ 0, 1, 0 }, // 1111 1101
{ 0, 1, 1 }, // 1111 1110
{ 0, 0, 0 }, // 1111 1111
};