浅析alsa声卡驱动中检测是否有1个元素被置位的小算法
#define SNDRV_MASK_BITS 64 /* we use so far 64bits only */
#define SNDRV_MASK_SIZE (SNDRV_MASK_BITS / 32)
#define SNDRV_MASK_MAX 256
struct snd_mask {
__u32 bits[(SNDRV_MASK_MAX+31)/32];
};
// 如下函数用来检测SNDRV_MASK_BITS个bit位数据中是否有多余1个bit被置位了[luther.gliethttp]
static inline int snd_mask_single(const struct snd_mask *mask)
{
int i, c = 0;
for (i = 0; i < SNDRV_MASK_SIZE; i++) {
if (! mask->bits[i]) // 如果当前32bits全0,那么表示空,continue到下一个32bits组
continue;
// 执行到这里说明该32bits位组中一定有>=1个bit被置位[luther.gliethttp],
// 下面继续判断该32bits位组中只有1个bit置位,还是多于1个bit.
if (mask->bits[i] & (mask->bits[i] - 1)) // 这是算法的核心,其实就是简单的利用了减法借位原理:
return 0; // 因为减1操作,会向高位借位,那么第1次出现1的高位,将因为借位置0,
// 而从第0位到第1次出现1之间的所有bits都将取反,而第1次出现1的位置到第31bit之间的数据将保持不变,比如:
// 只有1个bit置位:00001000,那么减1之后为00000111
// 多余1个bit置位:01001000,那么减1之后为01000111
// 所以如果mask->bits[i] & (mask->bits[i] - 1)非0,说明该32bits位组一定有2个或2个以上bit被置位
// 那么直接return 0;表示有多于1个bit都被置位[luther.gliethttp]
if (c) // 如果c非0,说明之前的mask->bits[0..i-1]的位组中已经有1个仅仅有1个bit
return 0; // 被置位的情况,所以加上i这次的,那么就表示mask->bits[]至少包含2个bit置位
// 所以直接return 0;表示有多于1个bit都被置位[luther.gliethttp]
// 如果执行到这里,说明当前i对应的mask->bits[i]这个32bits位组只有1个bit被置位.
c++;
}
// 表示<=1个bit被置位,都当作有1个bit置位[luther.gliethttp],
// 如果想细分是否真的有1个bit被置位,可以通过
// if (c) return 1;
return 1;
}
阅读(1063) | 评论(0) | 转发(3) |